java - 我应该如何设计我的线程,以便不需要实例化泛型?

标签 java multithreading generics

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

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;
    }
}

如何重新设计我的类,以便不需要实例化泛型类型,但我仍然可以在比较函数之间轻松切换?

最佳答案

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

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 方法,而不是构造函数注入(inject)。或者,您也可以使用 Function ,或者实现您自己的工厂接口(interface)以坚持构造函数注入(inject)。

关于java - 我应该如何设计我的线程,以便不需要实例化泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52416677/

相关文章:

java - 如何正确地将文件夹添加到 Eclipse 中的类路径中?

java - 使android apk文件中的java代码不可访问(不仅仅是混淆)

c# - 如何解决 .NET 中事件数量未知的线程同步问题?

java - 进化模拟 - 用于计时器事件处理的持久线程

java - 无锁地对映射结构进行并发读取访问

java - 如何捕获 Swing GUI 元素?

java - Gradle:使用 Spring Boot 依赖项构建 'fat jar'

java - 为什么我的 List<Integer> 中的元素是字符类型?

java - 获取List<T>的类

Java如何使方法参数接受子类类型和父类(super class)