You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xbean-scm@geronimo.apache.org by rm...@apache.org on 2013/10/28 10:33:45 UTC

svn commit: r1536292 - in /geronimo/xbean/trunk/xbean-finder/src: main/java/org/apache/xbean/finder/AnnotationFinder.java main/java/org/apache/xbean/finder/MultiThreadedAnnotationFinder.java test/java/org/apache/xbean/finder/ClassFinderDepthTest.java

Author: rmannibucau
Date: Mon Oct 28 09:33:44 2013
New Revision: 1536292

URL: http://svn.apache.org/r1536292
Log:
XBEAN-253 adding MultiThreadedAnnotationFinder

Added:
    geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/MultiThreadedAnnotationFinder.java
Modified:
    geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java
    geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java

Modified: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java?rev=1536292&r1=1536291&r2=1536292&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java (original)
+++ geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java Mon Oct 28 09:33:44 2013
@@ -50,6 +50,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -68,11 +69,11 @@ public class AnnotationFinder implements
 
     private final Set<Class<? extends Annotation>> metaroots = new HashSet<Class<? extends Annotation>>();
 
-    private final Map<String, List<Info>> annotated = new HashMap<String, List<Info>>();
+    protected final Map<String, List<Info>> annotated = newAnnotatedMap();
 
-    protected final Map<String, ClassInfo> classInfos = new HashMap<String, ClassInfo>();
-    protected final Map<String, ClassInfo> originalInfos = new HashMap<String, ClassInfo>();
-    private final List<String> classesNotLoaded = new ArrayList<String>();
+    protected final Map<String, ClassInfo> classInfos = newClassInfoMap();
+    protected final Map<String, ClassInfo> originalInfos = newClassInfoMap();
+    private final List<String> classesNotLoaded = new LinkedList<String>();
     private final int ASM_FLAGS = ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES;
     private final Archive archive;
     private final boolean checkRuntimeAnnotation;
@@ -81,6 +82,7 @@ public class AnnotationFinder implements
         this.archive = new SubArchive(classNames);
         this.checkRuntimeAnnotation = parent.checkRuntimeAnnotation;
         this.metaroots.addAll(parent.metaroots);
+
         for (Class<? extends Annotation> metaroot : metaroots) {
             final ClassInfo info = parent.classInfos.get(metaroot.getName());
             if (info == null) continue;
@@ -92,7 +94,7 @@ public class AnnotationFinder implements
             readClassDef(info);
         }
 
-        resolveAnnotations(parent, new ArrayList<String>());
+        resolveAnnotations(parent, new LinkedList<String>());
         for (ClassInfo classInfo : classInfos.values()) {
             if (isMetaRoot(classInfo)) {
                 try {
@@ -114,6 +116,14 @@ public class AnnotationFinder implements
         }
     }
 
+    protected Map<String, List<Info>> newAnnotatedMap() {
+        return new HashMap<String, List<Info>>();
+    }
+
+    protected Map<String, ClassInfo> newClassInfoMap() {
+        return new HashMap<String, ClassInfo>();
+    }
+
     /**
      *
      * @param archive
@@ -217,7 +227,7 @@ public class AnnotationFinder implements
 
     public AnnotationFinder enableMetaAnnotations() {
         // diff new and old lists
-        resolveAnnotations(new ArrayList<String>());
+        resolveAnnotations(new LinkedList<String>());
 
         linkMetaAnnotations();
 
@@ -335,7 +345,7 @@ public class AnnotationFinder implements
         return className.equals(simpleName) || className.endsWith("." + simpleName) || className.endsWith("$" + simpleName);
     }
 
-    private void linkParent(ClassInfo classInfo) {
+    protected void linkParent(ClassInfo classInfo) {
         if (classInfo.superType == null) return;
         if (classInfo.superType.equals("java.lang.Object")) return;
 
@@ -363,13 +373,15 @@ public class AnnotationFinder implements
             classInfo.superclassInfo = parentInfo;
         }
 
-        if (!parentInfo.subclassInfos.contains(classInfo)) {
-            parentInfo.subclassInfos.add(classInfo);
+        synchronized (parentInfo.subclassInfos) {
+            if (!parentInfo.subclassInfos.contains(classInfo)) {
+                parentInfo.subclassInfos.add(classInfo);
+            }
         }
     }
 
-    private void linkInterfaces(ClassInfo classInfo) {
-        final List<ClassInfo> infos = new ArrayList<ClassInfo>();
+    protected void linkInterfaces(ClassInfo classInfo) {
+        final List<ClassInfo> infos = new LinkedList<ClassInfo>();
 
         if (classInfo.clazz != null) {
             final Class<?>[] interfaces = classInfo.clazz.getInterfaces();
@@ -388,17 +400,19 @@ public class AnnotationFinder implements
                 }
             }
         } else {
-            for (String className : classInfo.interfaces) {
-                ClassInfo interfaceInfo = classInfos.get(className);
+            synchronized (classInfo.interfaces) {
+                for (String className : classInfo.interfaces) {
+                    ClassInfo interfaceInfo = classInfos.get(className);
 
-                if (interfaceInfo == null) {
-                    readClassDef(className);
-                }
+                    if (interfaceInfo == null) {
+                        readClassDef(className);
+                    }
 
-                interfaceInfo = classInfos.get(className);
+                    interfaceInfo = classInfos.get(className);
 
-                if (interfaceInfo != null) {
-                    infos.add(interfaceInfo);
+                    if (interfaceInfo != null) {
+                        infos.add(interfaceInfo);
+                    }
                 }
             }
         }
@@ -432,7 +446,7 @@ public class AnnotationFinder implements
 
     public List<Package> findAnnotatedPackages(Class<? extends Annotation> annotation) {
         classesNotLoaded.clear();
-        List<Package> packages = new ArrayList<Package>();
+        List<Package> packages = new LinkedList<Package>();
         List<Info> infos = getAnnotationInfos(annotation.getName());
         for (Info info : infos) {
             if (info instanceof PackageInfo) {
@@ -453,7 +467,7 @@ public class AnnotationFinder implements
 
     public List<Class<?>> findAnnotatedClasses(Class<? extends Annotation> annotation) {
         classesNotLoaded.clear();
-        List<Class<?>> classes = new ArrayList<Class<?>>();
+        List<Class<?>> classes = new LinkedList<Class<?>>();
         List<Info> infos = getAnnotationInfos(annotation.getName());
         for (Info info : infos) {
             if (info instanceof ClassInfo) {
@@ -476,7 +490,7 @@ public class AnnotationFinder implements
         classesNotLoaded.clear();
         Set<Class<?>> classes = findMetaAnnotatedClasses(annotation, new HashSet<Class<?>>());
 
-        List<Annotated<Class<?>>> list = new ArrayList<Annotated<Class<?>>>();
+        List<Annotated<Class<?>>> list = new LinkedList<Annotated<Class<?>>>();
 
         for (Class<?> clazz : classes) {
             if (Annotation.class.isAssignableFrom(clazz) && isMetaAnnotation((Class<? extends Annotation>) clazz)) continue;
@@ -554,7 +568,7 @@ public class AnnotationFinder implements
      */
     public List<Class<?>> findInheritedAnnotatedClasses(Class<? extends Annotation> annotation) {
         classesNotLoaded.clear();
-        List<Class<?>> classes = new ArrayList<Class<?>>();
+        List<Class<?>> classes = new LinkedList<Class<?>>();
         List<Info> infos = getAnnotationInfos(annotation.getName());
         for (Info info : infos) {
             try {
@@ -606,8 +620,8 @@ public class AnnotationFinder implements
 
     public List<Method> findAnnotatedMethods(Class<? extends Annotation> annotation) {
         classesNotLoaded.clear();
-        List<ClassInfo> seen = new ArrayList<ClassInfo>();
-        List<Method> methods = new ArrayList<Method>();
+        List<ClassInfo> seen = new LinkedList<ClassInfo>();
+        List<Method> methods = new LinkedList<Method>();
         List<Info> infos = getAnnotationInfos(annotation.getName());
         for (Info info : infos) {
             if (info instanceof MethodInfo && !info.getName().equals("<init>")) {
@@ -649,7 +663,7 @@ public class AnnotationFinder implements
         classesNotLoaded.clear();
         
         final Set<ClassInfo> seen = checkRuntimeAnnotation ? new HashSet<ClassInfo>() : null;
-        final List<Parameter<Method>> result = new ArrayList<Parameter<Method>>();
+        final List<Parameter<Method>> result = new LinkedList<Parameter<Method>>();
         for (Info info : getAnnotationInfos(annotation.getName())) {
             if (!(info instanceof ParameterInfo)) {
                 continue;
@@ -696,7 +710,7 @@ public class AnnotationFinder implements
 
         Set<Method> methods = findMetaAnnotatedMethods(annotation, new HashSet<Method>(), new HashSet<String>());
 
-        List<Annotated<Method>> targets = new ArrayList<Annotated<Method>>();
+        List<Annotated<Method>> targets = new LinkedList<Annotated<Method>>();
 
         for (Method method : methods) {
             targets.add(new MetaAnnotatedMethod(method));
@@ -757,7 +771,7 @@ public class AnnotationFinder implements
 
         Set<Field> fields = findMetaAnnotatedFields(annotation, new HashSet<Field>(), new HashSet<String>());
 
-        List<Annotated<Field>> targets = new ArrayList<Annotated<Field>>();
+        List<Annotated<Field>> targets = new LinkedList<Annotated<Field>>();
 
         for (Field field : fields) {
             targets.add(new MetaAnnotatedField(field));
@@ -815,8 +829,8 @@ public class AnnotationFinder implements
 
     public List<Constructor> findAnnotatedConstructors(Class<? extends Annotation> annotation) {
         classesNotLoaded.clear();
-        List<ClassInfo> seen = new ArrayList<ClassInfo>();
-        List<Constructor> constructors = new ArrayList<Constructor>();
+        List<ClassInfo> seen = new LinkedList<ClassInfo>();
+        List<Constructor> constructors = new LinkedList<Constructor>();
         List<Info> infos = getAnnotationInfos(annotation.getName());
         for (Info info : infos) {
             if (info instanceof MethodInfo && info.getName().equals("<init>")) {
@@ -857,7 +871,7 @@ public class AnnotationFinder implements
         classesNotLoaded.clear();
         
         final Set<ClassInfo> seen = checkRuntimeAnnotation ? new HashSet<ClassInfo>() : null;
-        final List<Parameter<Constructor<?>>> result = new ArrayList<Parameter<Constructor<?>>>();
+        final List<Parameter<Constructor<?>>> result = new LinkedList<Parameter<Constructor<?>>>();
         for (Info info : getAnnotationInfos(annotation.getName())) {
             if (!(info instanceof ParameterInfo)) {
                 continue;
@@ -903,8 +917,8 @@ public class AnnotationFinder implements
 
     public List<Field> findAnnotatedFields(Class<? extends Annotation> annotation) {
         classesNotLoaded.clear();
-        List<ClassInfo> seen = new ArrayList<ClassInfo>();
-        List<Field> fields = new ArrayList<Field>();
+        List<ClassInfo> seen = new LinkedList<ClassInfo>();
+        List<Field> fields = new LinkedList<Field>();
         List<Info> infos = getAnnotationInfos(annotation.getName());
         for (Info info : infos) {
             if (info instanceof FieldInfo) {
@@ -943,7 +957,7 @@ public class AnnotationFinder implements
 
     public List<Class<?>> findClassesInPackage(String packageName, boolean recursive) {
         classesNotLoaded.clear();
-        List<Class<?>> classes = new ArrayList<Class<?>>();
+        List<Class<?>> classes = new LinkedList<Class<?>>();
         for (ClassInfo classInfo : classInfos.values()) {
             try {
                 if (recursive && classInfo.getPackageName().startsWith(packageName)) {
@@ -965,7 +979,7 @@ public class AnnotationFinder implements
 
         final ClassInfo classInfo = classInfos.get(clazz.getName());
 
-        List<Class<? extends T>> found = new ArrayList<Class<? extends T>>();
+        List<Class<? extends T>> found = new LinkedList<Class<? extends T>>();
 
         if (classInfo == null) return found;
 
@@ -991,7 +1005,7 @@ public class AnnotationFinder implements
     private <T> List<Class<? extends T>> _findSubclasses(Class<T> clazz) {
         if (clazz == null) throw new NullPointerException("class cannot be null");
 
-        List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>();
+        List<Class<? extends T>> classes = new LinkedList<Class<? extends T>>();
 
 
         for (ClassInfo classInfo : classInfos.values()) {
@@ -1030,7 +1044,7 @@ public class AnnotationFinder implements
         List<ClassInfo> infos = collectImplementations(interfaceName);
 
         // Collect all subclasses of implementations
-        List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>();
+        List<Class<? extends T>> classes = new LinkedList<Class<? extends T>>();
         for (ClassInfo info : infos) {
             try {
                 final Class<? extends T> impl = (Class<? extends T>) info.get();
@@ -1052,26 +1066,28 @@ public class AnnotationFinder implements
     }
 
     private List<ClassInfo> collectImplementations(String interfaceName) {
-        final List<ClassInfo> infos = new ArrayList<ClassInfo>();
+        final List<ClassInfo> infos = new LinkedList<ClassInfo>();
 
         for (ClassInfo classInfo : classInfos.values()) {
 
-            if (classInfo.interfaces.contains(interfaceName)) {
+            synchronized (classInfo.interfaces) {
+                if (classInfo.interfaces.contains(interfaceName)) {
 
-                infos.add(classInfo);
+                    infos.add(classInfo);
 
-                try {
+                    try {
 
-                    final Class clazz = classInfo.get();
+                        final Class clazz = classInfo.get();
 
-                    if (clazz.isInterface() && !clazz.isAnnotation()) {
+                        if (clazz.isInterface() && !clazz.isAnnotation()) {
 
-                        infos.addAll(collectImplementations(classInfo.name));
+                            infos.addAll(collectImplementations(classInfo.name));
 
-                    }
+                        }
 
-                } catch (ClassNotFoundException ignore) {
-                    // we'll deal with this later
+                    } catch (ClassNotFoundException ignore) {
+                        // we'll deal with this later
+                    }
                 }
             }
         }
@@ -1113,7 +1129,7 @@ public class AnnotationFinder implements
     }
 
     protected void readClassDef(Class clazz) {
-        List<Info> infos = new ArrayList<Info>();
+        List<Info> infos = new LinkedList<Info>();
 
         Package aPackage = clazz.getPackage();
         if (aPackage != null) {
@@ -1180,7 +1196,7 @@ public class AnnotationFinder implements
     }
 
     public class SubArchive implements Archive {
-        private List<Entry> classes = new ArrayList<Entry>();
+        private List<Entry> classes = new LinkedList<Entry>();
 
         public SubArchive(String... classes) {
             for (String name : classes) {
@@ -1224,7 +1240,7 @@ public class AnnotationFinder implements
     }
 
     public class Annotatable {
-        private final List<AnnotationInfo> annotations = new ArrayList<AnnotationInfo>();
+        private final List<AnnotationInfo> annotations = new LinkedList<AnnotationInfo>();
 
         public Annotatable(AnnotatedElement element) {
             for (Annotation annotation : getAnnotations(element)) {
@@ -1428,7 +1444,7 @@ public class AnnotationFinder implements
         private final ClassInfo declaringClass;
         private final String descriptor;
         private final String name;
-        private final List<List<AnnotationInfo>> parameterAnnotations = new ArrayList<List<AnnotationInfo>>();
+        private final List<List<AnnotationInfo>> parameterAnnotations = new LinkedList<List<AnnotationInfo>>();
         private final List<ParameterInfo> parameters = new SingleLinkedList<ParameterInfo>();
         private Member method;
 
@@ -1479,7 +1495,7 @@ public class AnnotationFinder implements
         public List<AnnotationInfo> getParameterAnnotations(int index) {
             if (index >= parameterAnnotations.size()) {
                 for (int i = parameterAnnotations.size(); i <= index; i++) {
-                    List<AnnotationInfo> annotationInfos = new ArrayList<AnnotationInfo>();
+                    List<AnnotationInfo> annotationInfos = new LinkedList<AnnotationInfo>();
                     parameterAnnotations.add(i, annotationInfos);
                 }
             }
@@ -1514,7 +1530,7 @@ public class AnnotationFinder implements
             org.objectweb.asm.commons.Method method = new org.objectweb.asm.commons.Method(name, descriptor);
 
             Class<?> clazz = this.declaringClass.get();
-            List<Class> parameterTypes = new ArrayList<Class>();
+            List<Class> parameterTypes = new LinkedList<Class>();
 
             for (Type type : method.getArgumentTypes()) {
                 String paramType = type.getClassName();
@@ -1551,7 +1567,7 @@ public class AnnotationFinder implements
     public class ParameterInfo extends Annotatable implements Info {
         private final MethodInfo declaringMethod;
         private final int index;
-        private final List<AnnotationInfo> annotations = new ArrayList<AnnotationInfo>();
+        private final List<AnnotationInfo> annotations = new LinkedList<AnnotationInfo>();
         private Parameter<?> parameter;
 
         public ParameterInfo(MethodInfo parent, int index) {

Added: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/MultiThreadedAnnotationFinder.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/MultiThreadedAnnotationFinder.java?rev=1536292&view=auto
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/MultiThreadedAnnotationFinder.java (added)
+++ geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/MultiThreadedAnnotationFinder.java Mon Oct 28 09:33:44 2013
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.xbean.finder;
+
+import org.apache.xbean.finder.archive.Archive;
+import org.apache.xbean.finder.util.SingleLinkedList;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class MultiThreadedAnnotationFinder extends AnnotationFinder {
+    private ExecutorService executor = null;
+    private CountDownLatch subclassesLatch = null;
+    private CountDownLatch implementationsLatch = null;
+    private final int threads;
+
+    public MultiThreadedAnnotationFinder(final Archive archive, final boolean checkRuntimeAnnotation, final int threads) {
+        super(archive, checkRuntimeAnnotation);
+        this.threads = threads;
+    }
+
+    public MultiThreadedAnnotationFinder(final Archive archive, final int threads) {
+        super(archive);
+        this.threads = threads;
+    }
+
+    @Override
+    public AnnotationFinder enableFindImplementations() {
+        if (implementationsLatch == null) {
+            implementationsLatch = scan(new FindImplementationsFactory());
+        }
+        return this;
+    }
+
+    @Override
+    public AnnotationFinder enableFindSubclasses() {
+        if (subclassesLatch == null) {
+            subclassesLatch = scan(new FindSubclassesFactory());
+        }
+        return this;
+    }
+
+    private ExecutorService executor() {
+        if (executor == null) {
+            executor = Executors.newFixedThreadPool(threads, new DaemonThreadFactory());
+        }
+        return executor;
+    }
+
+    @Override
+    public <T> List<Class<? extends T>> findSubclasses(final Class<T> clazz) {
+        if (subclassesLatch == null) {
+            enableFindSubclasses();
+        }
+        join(subclassesLatch);
+
+        return super.findSubclasses(clazz);
+    }
+
+    @Override
+    public <T> List<Class<? extends T>> findImplementations(final Class<T> clazz) {
+        if (implementationsLatch == null) {
+            enableFindImplementations();
+        }
+        join(implementationsLatch);
+        return super.findImplementations(clazz);
+    }
+
+    private CountDownLatch scan(final ScanTaskFactory factory) {
+        final ClassInfo[] classes = classInfos.values().toArray(new ClassInfo[classInfos.size()]);
+        final ExecutorService es = executor();
+        final CountDownLatch latch = new CountDownLatch(classes.length);
+        for (final ClassInfo classInfo : classes) {
+            es.submit(factory.next(classInfo, latch));
+        }
+        return latch;
+    }
+
+    private void join(final CountDownLatch latch) {
+        try {
+            latch.await(1, TimeUnit.HOURS);
+        } catch (final InterruptedException e) {
+            // no-op
+        }
+    }
+
+    @Override
+    protected Map<String, ClassInfo> newClassInfoMap() {
+        return new ConcurrentHashMap<String, ClassInfo>();
+    }
+
+    @Override
+    protected Map<String, List<Info>> newAnnotatedMap() {
+        return new ConcurrentHashMap<String, List<Info>>();
+    }
+
+    @Override
+    protected List<Info> initAnnotationInfos(String name) {
+        List<Info> infos = annotated.get(name);
+        if (infos == null) {
+            infos = new SingleLinkedList<Info>();
+
+            final List<Info> old = ((ConcurrentMap<String, List<Info>>) annotated).putIfAbsent(name, infos);
+            if (old != null) {
+                infos = old;
+            }
+        }
+        return infos;
+    }
+
+    protected static class DaemonThreadFactory implements ThreadFactory {
+        private final String name = "xbean-finder-" + hashCode();
+        private final ThreadGroup group;
+        private final AtomicInteger ids = new AtomicInteger(0);
+
+        protected DaemonThreadFactory() {
+            final SecurityManager securityManager = System.getSecurityManager();
+            if (securityManager != null) {
+                group = securityManager.getThreadGroup();
+            } else {
+                group = Thread.currentThread().getThreadGroup();
+            }
+        }
+
+        // @Override
+        public Thread newThread(final Runnable runnable) {
+            final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+            Thread.currentThread().setContextClassLoader(AnnotationFinder.class.getClassLoader());
+            try {
+                final Thread thread = new Thread(group, runnable, name + " - " + ids.incrementAndGet());
+                if (!thread.isDaemon()) {
+                    thread.setDaemon(true);
+                }
+                if (thread.getPriority() != Thread.NORM_PRIORITY) {
+                    thread.setPriority(Thread.NORM_PRIORITY);
+                }
+                return thread;
+            } finally {
+                Thread.currentThread().setContextClassLoader(loader);
+            }
+        }
+    }
+
+    protected static abstract class ScanTask implements Runnable {
+        private final ClassInfo info;
+        private final CountDownLatch latch;
+
+        protected ScanTask(final ClassInfo info, final CountDownLatch latch) {
+            this.info = info;
+            this.latch = latch;
+        }
+
+        // @Override
+        public void run() {
+            try {
+                doRun(info);
+            } finally {
+                latch.countDown();
+            }
+        }
+
+        public abstract void doRun(final ClassInfo info);
+    }
+
+    protected static interface ScanTaskFactory {
+        ScanTask next(final ClassInfo info, CountDownLatch latch);
+    }
+
+    protected class FindImplementationsFactory implements ScanTaskFactory {
+        // @Override
+        public ScanTask next(final ClassInfo info, final CountDownLatch latch) {
+            return new FindImplementations(info, latch);
+        }
+    }
+
+    protected class FindSubclassesFactory implements ScanTaskFactory {
+        // @Override
+        public ScanTask next(final ClassInfo info, final CountDownLatch latch) {
+            return new FindSubclasses(info, latch);
+        }
+    }
+
+    protected class FindImplementations extends ScanTask {
+        public FindImplementations(final ClassInfo info, final CountDownLatch latch) {
+            super(info, latch);
+        }
+
+        @Override
+        public void doRun(final ClassInfo info) {
+            linkInterfaces(info);
+        }
+    }
+
+    protected class FindSubclasses extends ScanTask {
+        public FindSubclasses(final ClassInfo info, final CountDownLatch latch) {
+            super(info, latch);
+        }
+
+        @Override
+        public void doRun(final ClassInfo info) {
+            linkParent(info);
+        }
+    }
+}

Modified: geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java?rev=1536292&r1=1536291&r2=1536292&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java (original)
+++ geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java Mon Oct 28 09:33:44 2013
@@ -61,24 +61,36 @@ public class ClassFinderDepthTest extend
     }
 
     public void testFindSubclassesIncomplete() throws Exception {
-        final AnnotationFinder finder = new AnnotationFinder(new ClassesArchive(Crimson.class, Square.class)).link();
+        for (final AnnotationFinder finder : new AnnotationFinder[] {
+            new AnnotationFinder(new ClassesArchive(Crimson.class, Square.class)).link(),
+            new MultiThreadedAnnotationFinder(new ClassesArchive(Crimson.class, Square.class), maxThreads()).link()
+        }) {
+
+            assertSubclasses(finder, Color.class, Red.class, Crimson.class);
+            assertSubclasses(finder, Red.class, Crimson.class);
+            assertSubclasses(finder, Crimson.class);
 
-        assertSubclasses(finder, Color.class, Red.class, Crimson.class);
-        assertSubclasses(finder, Red.class, Crimson.class);
-        assertSubclasses(finder, Crimson.class);
-
-        assertSubclasses(finder, Shape.class, Square.class);
-        assertSubclasses(finder, Square.class);
+            assertSubclasses(finder, Shape.class, Square.class);
+            assertSubclasses(finder, Square.class);
+        }
     }
 
     public void testFindImplementations() throws Exception {
-        final AnnotationFinder finder = new AnnotationFinder(new ClassesArchive(Crimson.class, Square.class)).link();
+        for (final AnnotationFinder finder : new AnnotationFinder[] {
+            new AnnotationFinder(new ClassesArchive(Crimson.class, Square.class)).link(),
+            new MultiThreadedAnnotationFinder(new ClassesArchive(Crimson.class, Square.class), maxThreads()).link()
+        }) {
+
+            assertImplementations(finder, HSB.class, Color.class, Red.class, Crimson.class);
+            assertImplementations(finder, Hue.class, HSB.class, Color.class, Red.class, Crimson.class);
+            assertImplementations(finder, Saturation.class, HSB.class, Color.class, Red.class, Crimson.class);
+        }
+    }
 
-        assertImplementations(finder, HSB.class, Color.class, Red.class, Crimson.class);
-        assertImplementations(finder, Hue.class, HSB.class, Color.class, Red.class, Crimson.class);
-        assertImplementations(finder, Saturation.class, HSB.class, Color.class, Red.class, Crimson.class);
+    private static int maxThreads() {
+        return 2 * Runtime.getRuntime().availableProcessors();
     }
-    
+
     private void assertSubclasses(AnnotationFinder finder, Class<?> clazz, Class... subclasses) {
         final List<Class<?>> classes = new ArrayList(finder.findSubclasses(clazz));