2012-08-01 12 views
5

Mam obiekt ExecutorService puli pojedynczego wątku. W przyszłości w przyszłości zadania będą dodawane za pomocą metody submit(). Rozumiem, że zgłoszenie zostanie przesłane, dodaj przedłożoną wersję roboczą do końca listy zadań do wykonania. Jednak mam sytuację, w której w oparciu o boolean mogę chcieć przekazać uruchamianie do przodu zadań do wykonania. Nie chcę, aby to miało wpływ na bieżące zadanie, tylko że następnym zadaniem będzie to, które właśnie dałem. Przykładową metodę przedstawiono poniżej. Jak mam to zrobic?Java interject Runnable objects do ExecutorService

Dzięki

private ExecutorService singleLoadPool = Executors.newSingleThreadExecutor(); 
public void submitTask(Runnable run, boolean doNow) { 
    if (doNow) 
     singleLoadPool.submitFront(run); // This is the method I'm looking for 
    else 
     singleLoadPool.submit(run); 
} 

Odpowiedz

4

Moja preferencja byłaby użycie LinkedBlockingDeque. Obsługuje bezpośrednio wstawianie/usuwanie pozycyjne - putFirst(e)/takeFirst() i putLast(e)/takeLast() - co jest Twoim podstawowym wymaganiem - nie musisz implementować dla swoich elementów elementu Comparator. Również jest to ograniczone - co oznacza, że ​​zapewnia bezpieczeństwo przed OutOfMemoryError.

edit W odpowiedzi na najnowsze pytanie:

pierwsze, mają ExecutorService jak

ExecutorService executorService = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, workQueue);

Po drugie, ważne pytanie: co jest workQueue?

workQueue jest cienka owijka na dowolnej implementacji BlockingQueue, które delegaci wszystkich metod, aby instancji LinkedBlockingDeque że zawiera, oprócz metody offer(), które nazywa się jej przez ThreadPoolExecutor i który musi być nadpisane, jak to:

 public boolean offer(E e) { 
     if(doNow) 
     return linkedBlockingDequeInstance.offerFirst(e); 
     else 
     return linkedBlockingDequeInstance.offerLast(e); 
    } 

Oczywiście jeśli zastąpić dowolny sposób - trzeba uważać, aby zachować bezpieczeństwo wątków i jego ogólną contract.Definitely ten wymaga starannego przemyślenia i rygorystyczne testy.

+0

To jest dokładnie to, czego potrzebuję, dzięki – Jon

+0

Lepsze niż moje rozwiązanie :) –

+0

Więc miałem zamiar zaimplementować to i mam jeszcze jedno pytanie, jak dokładnie dodać zadania do kolejki? Czy muszę przesłonić ThreadPoolExecutor, ponieważ nie mogę po prostu dodać obiektów Runnable do LinkedBlockingDeque? – Jon

1

Myślę, że najlepszym sposobem na to byłoby instantiate a ThreadPoolExecutor z PriorityBlockingQueue. W szczególności używaj konstruktora PriorityBlockingQueue, który pobiera Comparator. Twój Comparator będzie tym, czego używasz do realizacji swojego "priorytetu".

PriorityBlockingQueue<Runnable> workQueue = new PriorityBlockingQueue<Runnable>(20, yourPriorityComparator); 
ExecutorService executorService = new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, workQueue); 
+0

Dziękuję za odpowiedź, czy mógłbyś podać przykład PriorytetuComparatora? – Jon

+0

Zobacz interfejs "Komparator" (obecnie powiązany z odpowiedzią). Prawdopodobnie będziesz musiał zaimplementować własny "Komparator", ale powinien on być stosunkowo prosty. –

+0

Moim problemem jest to, że nie rozumiem, jak wprowadzić moją wartość boolowską do Komparatora. Do kompilacji potrzebuję stworzyć klasę z następującą prywatną klasą runnableComparator, która implementuje Komparator . Komparator musi porównywać typy Runnable i nie może porównywać klas, które implementują Runnable i może istnieć tylko 1 Komparator, który musi być utworzony w instancji, aby można było utworzyć instancję ExecutorService, więc nie można przekazać do niej Boolean doNow. – Jon