2017-04-14 88 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

相關問題