我是否需要为每个线程创建新的Callable对象?

时间:2017-04-14 14:52:58

标签: java multithreading

以下是两个选项

1)创建一个Callable并多次提交

Callable<String> callable = new MyCallable();
        for(int i=0; i< 100; i++){
           Future<String> future = executor.submit(callable);
            list.add(future);
        } 

2)为每个线程创建多个Callables

 for(int i=0; i< 100; i++){
        Future<String> future = executor.submit(new MyCallable());
        list.add(future);
    } 

最佳做法是什么?

1 个答案:

答案 0 :(得分:5)

如果您的MyCallable 线程安全类,那么您可以重复使用相同的实例,否则,您最终会遇到竞争条件且不一致结果。

换句话说,如果您的MyCallable 尝试保留任何未正确同步的状态,那么您就无法使用相同的实例

例如,在下面的MyCallable类中,您无法在多个线程中重复使用相同的实例(即,您无法像executor.submit(singleInstance)那样共享它:)

//Non-Thread Safe Callable implementation
public class MyCallable implements Callable<String> {

    private int i;

    @Override
    public String call() throws Exception {
         i++; //RACE CONDITION
         System.out.println(i);
         return String.valueOf(i);
    }
}

如果您将int替换为AtomicInteger,如下所示,那么您可以重复使用相同的实例:

//Thread Safe Callable implementation
public class MyThreadSafeCallable implements Callable<String> {

    private AtomicInteger i = new AtomicInteger(0);

    @Override
    public String call() throws Exception {
         int value = i.incrementAndGet();
         System.out.println(value);
         return String.valueOf(value);
    }
}

所以,这里要注意的重点是,如果你想重用Callable的同一个实例,你需要确保它是线程安全的。否则,您需要将多个Callable个实例提交到ExecutorService