2017-04-14 2 views
2

Hier sind die beiden OptionenMuss ich ein neues Callable-Objekt für jeden Thread erstellen?

1) Erstellen Sie ein Callable und legt ihn mehrfach

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

2) für jeden Thread mehrere Callables erstellen

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

Was ist die beste Praxis?

+0

Sie benötigen verschiedene aufrufbare Objekte. – jn1kk

+0

Danke. das ist was ich dachte. Allerdings gibt es hier ein Beispiel http://www.journaldev.com/1090/java-callable-future-example, das mich verwirrt. Es verwendet eine aufrufbare – john

+1

@ jn1kk - Es hängt davon ab, was diese Klasse tut. Es ist nichts an sich falsch, dasselbe Callable aus mehreren Threads aufzurufen. –

Antwort

4

Wenn Ihre MyCallable ist Thread-sichere Klasse dann können Sie die gleiche Instanz davon wiederverwenden, andernfalls werden Sie sich mit Rennbedingungen und inkonsistenten Ergebnissen beenden.

Mit anderen Worten, wenn Ihr MyCallableversucht, einen Zustand zu halten, der nicht richtig synchronisiert ist, dann können Sie nicht dieselbe Instanz verwenden.

Zum Beispiel die folgenden MyCallable Klasse, man kann nicht die gleiche Instanz über mehrere Threads Wiederverwendung (dh, können Sie es nicht wie executor.submit(singleInstance) teilen):

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

Während, wenn Sie int ersetzen mit AtomicInteger , wie unten gezeigt, dann können Sie die gleiche Instanz wiederverwenden:

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

der wichtige Punkt So, hier zu beachten ist, dass, wenn Sie die gleiche Instanz von Callable, y wiederverwenden wollen Sie müssen sicherstellen, dass es threadsicher ist. Andernfalls müssen Sie mehrere Callable Instanzen an die ExecutorService gesendet werden.

Verwandte Themen