代码之家  ›  专栏  ›  技术社区  ›  Cecilia

我应该如何设计我的线程,使我不需要实例化一个泛型?

  •  2
  • Cecilia  · 技术社区  · 6 年前

    我有几个线程类使用不同的比较方法。我将它们实现为扩展一个抽象类。例如,

    public abstract class MatcherThread implements Runnable{
        List<String> clusters;
        int output;
    
        public MatcherThread(List<String> clusters){
            this.clusters = clusters;
        }
    
        public void run()
        {
            for(List<String> c: clusters) {
                compare(c);
            }
        }
    
        public int getOutput(){
           return output;
        }
    
        protected abstract void compare(String c);
    }
    
    public class MaxLength extends MatcherThread{
        public MaxLength(List<String> clusters){
          super(clusters);
          this.output = Integer.MAX_VALUE;
        }
    
        protected void compare(String c){
          if(c.length() > output) output = c.length();
        }
    }
    
    public class MinLength extends MatcherThread{
        public MinLength(List<String> clusters){
          super(clusters);
          this.output = 0;
        }
    
        protected void compare(String c){
          if(c.length() < output) output = c.length();
        }
    }
    

    import java.util.*;
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Matcher<T extends MatcherThread>{
    
         protected List<Integer> runAll(List<String> clusters, int nthreads) {
            int n = clusters.size();
            int poolSize = nthreads;
            int step = n/poolSize;
            ExecutorService es = Executors.newFixedThreadPool(poolSize);
            List<T> tasks = new ArrayList<T>();
            for (int i = 0; i < poolSize; i++) {
                int start = i*step;
                int end = i == poolSize -1 ? n: (i+1)*step;
    
                List<List<String>> subcluster = new ArrayList<List<String>>(){{
                    for (int ind=start; ind < end; ind++) add(clusters(ind));
                }};
    
                T task = new T(subcluster); //This is not allowed.
                tasks.add(task);
            }
            CompletableFuture<?>[] futures = tasks.stream().map(task -> CompletableFuture.runAsync(task, es)).toArray(CompletableFuture[]::new);
            CompletableFuture.allOf(futures).join();
            es.shutdown();
    
            List<Integer> output = new List<Integer>();
            for(T t : tasks) {
                output.add(t.getOutput());
            }
            return output;
        }
    }
    

    如何重新设计类,这样就不必实例化泛型类型,但仍然可以在比较函数之间轻松切换?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Cecilia    6 年前

    在这种情况下,您通常会向Matcher提供某种工厂,该工厂负责创建适当的线程。在Java8中,您可以使用 Supplier 接口:

    public class Matcher {
    
        private final Supplier<? extends MatcherThread> threadSupplier;
    
        public Matcher(Supplier<? extends MatcherThread> threadSupplier) {
            this.threadSupplier = threadSupplier;
        }
    
         protected List<Integer> runAll(List<String> clusters, int nthreads) {
    
            // …
            MatcherThread task = threadSupplier.get();
            task.setSubcluster(subcluster); // refactor to allow setter injection
            tasks.add(task);
            // …
    
        }
    
    }
    

    Matcher matcher = new Matcher(() -> new MaxLength());
    

    这假设您添加了 setSubcluster 方法,而不是构造函数注入。或者,您也可以使用 Function