2017-04-14 55 views
2

这里有两个选项我是否需要为每个线程创建新的Callable对象?

1)创建一个可赎回和多次

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

2提交)为每个线程

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

什么是最好的实践中创建多个可调用?

+0

您需要不同的可调用对象。 – jn1kk

+0

谢谢。这是我的想法。然而,这里有一个例子http://www.journaldev.com/1090/java-callable-future-example让我困惑。它使用一个可调用的函数 – john

+1

@ jn1kk - 这取决于该类的功能。从多个线程中调用相同的Callable本质上没有任何问题。 –

回答

4

如果您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); 
    } 
} 

如果用AtomicInteger替换int而,如下图所示,那么你就可以重复使用相同的实例:

//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,Y相同的实例你需要确保它是线程安全的。否则,您需要将多个Callable实例提交到ExecutorService

相关问题