来自Callable而不是Runnable的新线程?

时间:2018-09-10 12:54:00

标签: java multithreading

线程通常从Runnable s创建。有没有一种方法可以从Callable创建线程?

public class AddNumImmediately implements Callable {
    private int minRange;
    private int maxRange;
    private Set<Integer> primeNumberList;
    private int step;

    public AddNumImmediately(int minRange, int maxRange, Set<Integer> primeNumberList, int step) {
        this.minRange = minRange;
        this.maxRange = maxRange;
        this.primeNumberList = primeNumberList;
        this.step = step;
    }

    @Override
    public Object call() {
        for (int i = minRange; i <= maxRange; i += step) {
            if (PrimeChecker.isPrimeNumber(i)) {
                primeNumberList.add(i);
            }
        }
        return primeNumberList;
    }
}

然后我尝试通过线程运行Callable:

public void setup(int min, int max, int threadNumber) throws InterruptedException {
    Set<Integer> primeNumberList = new LinkedHashSet<>();
    List<Thread> threadList = new ArrayList<>();

    for (int i = 0; i < threadNumber; i++) {
        threadList.add(new Thread(String.valueOf(new AddNumImmediately(min, max, primeNumberList, threadNumber))));
    }
    for (Thread thread : threadList) {
        thread.start();
    }

    for (Thread thread : threadList) {
        thread.join();
    }
    System.out.println(primeNumberList);
}

我知道Callable可以由Executor运行,但是有可能通过Thread运行它们吗?

4 个答案:

答案 0 :(得分:2)

您使用的Callable错误。可调用对象返回<V>,当通过Future<V>提交时,它将变为ExecutorService,如果不使用它们,则选择Runnable

可通话

  

返回结果并可能引发异常的任务。实施者   定义一个没有参数的单一方法,称为call。

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

可运行

  

Runnable接口应该由其   实例旨在由线程执行。上课必须   定义一个没有参数的方法称为run。

https://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html

因此,可调用对象的正确方法是返回一个Set<Integer>并将这些期货合并到您的primeNumberList中。

答案 1 :(得分:2)

  

是否可以通过Callable创建线程?

简短的回答:否。Thread API要求使用Runnable而不是Callable

您可以使用Runnable的{​​{1}}包装器解决此问题,尽管从Callable获取结果有点混乱!一个更好的主意是使用Callable。这样就可以避免创建过多线程以及(或者)管理自己的线程池的问题。

注意到您的示例实际上并不需要ExecutorService是很有意义的。您将返回Callable构造函数中提供的Set。调用者可以简单地保留对该AddNumImmediately对象的引用。

答案 2 :(得分:0)

您可以用Callable包裹Runnable。使用此帮助程序功能可从Thread创建Callable

public static Thread createThreadFromCallable(@NonNull Callable<?> callable) {
    return new Thread(() -> {
        try {
            callable.call();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
}

答案 3 :(得分:0)

您不能从可调用对象创建新线程。就在那里。对于一个新线程,线程必须出现。 据说您可以将 FurtureTask 与 callable 和 Thread 一起使用来获取结果。你可以试试这样的:

FutureTask<String> f1 = new FutureTask<String>(new Callable<String>() {
    public String call() throws InterruptedException {
        Thread.sleep(1000);
        return "A constant from " + Thread.currentThread().getName();
    }
});

Thread t = new Thread(f1);
t.start();
System.out.println("Calling Get " + Thread.currentThread().getName());
System.out.println(f1.get());
System.out.println("Got Get");

会给你输出:

调用 Get main

来自 Thread-0 的常量

得到了