2015-11-17 42 views
5

Chcę utworzyć pulę wątków buforowanych, ale działa ona jako stała. Obecnie mam ten kod:Pula nici nie zmienia rozmiaru

public class BackgroundProcesses { 

    public static void main(String[] args) throws InterruptedException, ExecutionException { 
     //ExecutorService threadPool2 = Executors.newCachedThreadPool(); 
     ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); 
     for (int i = 0; i < 800; i++) { 
      Callable<String> task = new Task(); 
      threadPool.submit(task); 
     } 
    } 
} 

class Task implements Callable<String> { 

    @Override 
    public String call() throws Exception { 
     Thread.sleep(100); 
     System.out.println(Thread.currentThread().getName() + " is ready"); 
     return ""; 
    } 
} 

Jeśli uruchomić kod otrzymuję wyjścia:

pool-1-thread-1 is ready 
pool-1-thread-2 is ready 
pool-1-thread-1 is ready 
pool-1-thread-2 is ready 
... 

znaczenie tylko 2 wątki wykonują całą pracę i brak nowych wątków roboczych są dodawane do puli. Czy wątek nie powinien odradzać więcej wątków, jeśli zadania czekają w kolejce (do 10 w moim przypadku)?

Nie chcę używać Executors.newCachedThreadPool(), ponieważ nie ma praktycznie górnego limitu maksymalnych wątków i ma on corePoolSize 0. Chcę mieć zawsze gotowe wątki dla lepszej reakcji.

----- edit 1 -----

Dziękuję Aleksey za odpowiedź. Ustawienie zdolności do kolejkowania powoduje, że zachowuje się zgodnie z oczekiwaniami, ale teraz mam nowy problem.

Ilość zadań wykonywanych w tle jest bardzo różna. W większości przypadków 0, ale można przejść do 50 równoczesnych zadań przez krótki czas. Jaki byłby skuteczny sposób radzenia sobie z tym? Należy pamiętać, że większość zadań wykonywanych w tle byłaby krótkotrwała (< 1s), ale także kilka długotrwałych zadań (> 1min).

Jeśli mogę ustawić puli wątków się tak:

ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10)); 

I najprawdopodobniej dostać RejectedExecutionException z wykorzystaniem piku. Jednak jeśli ustawić puli wątków się tak:

ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200)); 

Następnie żadnych nowych wątków roboczych nigdy nie będzie dodana, ponieważ kolejka nie będzie max out.

Procesor ma co najmniej 4 rdzenie, więc moim zdaniem byłoby to marnotrawstwem. Przez większość czasu nie ma żadnych zadań wykonywanych w tle (80% więcej czasu), więc utrzymywanie stałej puli wątków byłoby w moim mniemaniu marnotrawstwem.

Odpowiedz

4

ThreadPoolExecutor Javadoc mówi:

Gdy nowe zadanie zostanie złożony w metodzie execute (Runnable), a mniej niż corePoolSize wątków są uruchomione, nowy wątek jest stworzony do obsłużyć żądania, nawet jeśli inna wątki robocze są bezczynne. Jeśli nie ponad corePoolSize ale mniej niż maximumPoolSize wątków uruchomiony nowy wątek zostaną utworzone tylko wtedy, gdy kolejka jest pełna

Twój LinkedBlockingQueue nigdy nie jest pełna, bo nie ma górnej granicy liczby elementów. Zmiana new LinkedBlockingQueue() na new LinkedBlockingQueue(10) rozwiąże to.

+0

Dzięki za wyczyszczenie tego. Ale teraz otrzymuję wyjątek RejectedExecutionException (rozmiar puli = 10, aktywne wątki = 10, zadania w kolejce = 10), ponieważ kolejka zostaje wypełniona i wszystkie aktywne wątki są również używane. –