2016-06-03 12 views
0

Erster Fall: Sagen wir, Sie haben eine Menge Aufgaben, die alle ein Ergebnis irgendeiner Art zurückgeben, lassen Sie es einfach "Ergebnis" für jetzt nennen, und diese müssen alle sein in einer Arraylist gespeichert. Es gibt zwei Möglichkeiten:java concurrency Gemeinsame Daten mit Runnable vs Callable und lokale Daten

1) Erstellen Sie eine Arraylist im Hauptverfahren und verwenden Runnables mit Zugriff auf die freigegebene Liste und einer synchronisierten Methode add

2) eine Arraylist im Hauptverfahren Erstellen und Verwenden von abrufbaren die auszuführen Aufgabe und geben Sie das Ergebnis zurück und lassen Sie die Hauptmethode das Ergebnis zu seiner Liste hinzufügen.

Gibt es irgendwelche Leistungsunterschiede zwischen den beiden, da die runnable Notwendigkeit synchronisiert Zugriffe, aber die Callables nicht?

Dann zum zweiten Fall: Sagen wir jetzt, jede Aufgabe erzeugt eine "kleine" Arraylist, sagen wir weniger als 10 Elemente pro Aufgabe. Dies gibt wiederum zwei Optionen:

1) Eine Arraylist in main und Runnables mit Zugriff auf die freigegebene Liste, die Ergebniselemente hinzufügen, wann immer generiert.

2) Eine ArrayList in main und callables> mit jeweils einer eigenen lokalen Arraylist, die die Ergebnisse speichert, bis die Aufgabe beendet ist und dann in main wird addAll verwendet, um das gefundene Ergebnis hinzuzufügen.

Gleiche Frage wie zuvor, was sind die Leistungsunterschiede?

Aus Gründen der Übersichtlichkeit, Leistung sowohl in Bezug auf die Geschwindigkeit (einige Synchronisationsprobleme etc.) und in Bezug auf Speicher (verwenden die Callables viel mehr Speicher aufgrund der lokalen kleinen Arraylist oder ist dies klein bis vernachlässigbar) ?

+0

Warum braucht man es eine Arraylist sein? –

+0

abhängig von einer Implementierung ist eine schlechte Praxis, müssen Sie sich auf Schnittstellen statt –

+1

Es hängt von Ihrer Arbeitsbelastung. Wenn Sie viele kleine Aufgaben haben, sollten Sie sich Gedanken über den Sperr-Overhead machen. Wenn die Aufgaben lange dauern, sollte die erste Überlegung sauberer/lesbarer Code sein. – waltersu

Antwort

0
For the First Case: 
  1. Option Eins: Wenn wir Runnable Aufgaben verwenden, dann können wir nichts von run() Methode zurückgegeben. Also ich denke, diese Option wird nicht Ihren Anforderungen entsprechen.

  2. Option zwei: Callable Nach meinem Verständnis Ihrer Anforderung, Callable ist gute Kandidat. Aber es gibt eine kleine Änderung, Wir werden eine Liste von Future erstellen und für jede Callable-Aufgabe (die wir den Executors übermitteln) wird das Future-Ergebnis dieser Callable (siehe untenstehenden Code für Details) zu dieser Liste hinzugefügt. Wann immer wir das Ergebnis einer Aufgabe benötigen, können wir das Ergebnis aus der entsprechenden Zukunft erhalten.

Klasse MainTaskExecutor {

private static ExecutorService exe = Executors.newCachedThreadPool(); 
private static List<Future<Result>> futureResults = new ArrayList<>(); 

public static void main(String[] args) throws ExecutionException, InterruptedException { 
    Callable<Result> dummyTask =()-> { 
     System.out.println("Task is executed"); 
     Result dummyResult = new Result(); 
     return dummyResult; 
    }; 

    //Submit a task 
    submitTask(dummyTask); 

    //Getting result of "0" index 
    System.out.println(futureResults.get(0).get()); 
} 

private static void submitTask(Callable<Result> task) { 
    futureResults.add(exe.submit(task)); 
} 

private static Result getResult(int taskNumber) throws ExecutionException, InterruptedException { 
    return futureResults.get(taskNumber).get(); 
} 

}

class Result { 
    // data to be added 
}