2012-09-02 9 views
6

Próbuję zrozumieć klasy ThreadPoolExecutor. Przeczytałem to: answer i Javadoc. Ale moje eksperymenty nie zgadza się z tym opisem:Jak działa funkcja MaximumPoolSize ThreadPoolExecutor?

zainicjować puli wątków z fabryki do śledzenia identyfikatory

int tcounter = 0; 
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1, TimeUnit.MINUTES, 
     new ArrayBlockingQueue<Runnable>(1000), new ThreadFactory() { 

      @Override 
      public Thread newThread(Runnable r) { 
       return new mThread(tcounter++, r); 
      } 
     }); 

public class mThread extends Thread { 
    int id; 

    private mThread(int id, Runnable run) { 
     super(run); 
     GLog.e("created thread " + id); 
     this.id = id; 
    } 

} 

następnie zadanie:

public class mRunanble implements Runnable { 
    int value = 0; 

    private mRunanble(int value) { 
     super(); 
     this.value = value; 
    } 

    @Override 
    public void run() { 
     SystemClock.sleep(3000); 
     Thread t = Thread.currentThread(); 
     if (t instanceof mThread) { 

      GLog.e("Say " + (value) + " on thread " + ((mThread) t).id); 
     } 

    } 

} 

i przypisać przycisk a działanie :

executor.execute(new mRunanble(i++)); 

Ale spamuję ten przycisk, a trzeci wątek nigdy nie jest tworzony, więc co jest dla drugiego parametru w konstruktorze ThreadPoolExecutor (maximumPoolSize=4). Widziałem 4 wątki do utworzenia i 2 z nich do zabicia po 1 minucie zakończenia wykonywania

+0

Co jest 'Runa'? 'mRunanble'? – Jeffrey

+0

Tak, przepraszam, to jest teraz edytowane – Addev

+0

czy to dlatego, że twoje wątki śpią? być może zmiana twojego działania, aby zrobić zajęte czekanie da ci wynik, którego oczekujesz. – happymeal

Odpowiedz

2

W ThreadPoolExecutor maximumPoolSize pojawia się w obrazie, gdy corePoolSize nie jest niewystarczające do wykonania zadań i jeśli wszystkie nie są zajęte przez zadania, tworzony jest tylko jeden bieżnik, aby wykonać zadanie. To nie może wzrosnąć do maxPoolSize.

Edytuj brakuje Ci idei maxPoolsize. Przeczytaj poniższy link.

http://www.bigsoft.co.uk/blog/index.php/2009/11/27/rules-of-a-threadpoolexecutor-pool-size

+0

Ale wszystkie podstawowe wątki OP * są * zajęte przez zadania. – Jeffrey

+0

Więc kiedy spamuję przycisk dodatkowe 2 wątki do momentu, aż maxPoolSize powinien zostać stworzony? – Addev

+0

zaktualizowano odpowiedź plz check. – amicngh

4

Od API dla ThreadPoolExecutor:

Jeśli istnieje więcej niż corePoolSize ale mniej niż maximumPoolSize wątki uruchomione, nowy wątek zostanie utworzona tylko wtedy, gdy kolejka jest pełny.

Twoja kolejka nigdy się nie wypełnia, ponieważ ma pojemność 1000. Jeśli zmienisz pojemność na 1, zobaczysz, że są tworzone Thread s.

Klasa Executors używa SynchronousQueue dla swoich metod newCachedThreadPool, więc warto rozważyć użycie jej również.

+0

Jeśli zmniejszam wartość, otrzymuję wartość java.util.concurrent.RejectedExecutionException – Addev

+1

, gdy tylko zmniejszysz liczbę najpierw do limitu maxPoolSize, a następnie odrzucisz zadania. Możesz także wydrukować rozmiar puli tuż przed tym wyjątkiem, który będzie równy do maxpoolsize. – amicngh

0

Aby utworzyć nową dodatkową pula wątków wątek (rozszerzyć wielkość puli według maximumPoolSize parametr) spróbuj wykonać ten prosty przykład:

public class Main { 

    public static void main(String[] args) throws InterruptedException { 

     ThreadPoolExecutor tpe = new ThreadPoolExecutor(
       1, 2, 500, TimeUnit.MILLISECONDS, 
       new LinkedBlockingQueue<>(1)); 
     System.out.println("init pool size= " + tpe.getPoolSize() + ", queue size=" + tpe.getQueue().size()); 

     tpe.execute(new Task("1st", 10000)); 
     Thread.sleep(1000); 
     print(tpe, "1st"); 

     tpe.execute(new Task("2nd", 0)); 
     Thread.sleep(1000); 
     print(tpe, "2nd"); 

     tpe.execute(new Task("3d", 2000)); 
     Thread.sleep(1000); 
     print(tpe, "3d"); 

     while (tpe.getPoolSize()>1) {   
      Thread.sleep(100); 
     } 
     System.out.println("pool size= " + tpe.getPoolSize() + ", queue size=" + tpe.getQueue().size()); 
     tpe.shutdown(); 
    } 

    private static void print(ThreadPoolExecutor tpe, String name) { 
     System.out.println("After " + name + " execute - pool size= " + tpe.getPoolSize() + ", queue=" + tpe.getQueue()); 
    } 

    private static class Task implements Runnable { 

     private final String name; 
     private final long time; 

     Task(String name, long time) { 
      this.name = name; 
      this.time = time; 
     } 

     @Override 
     public void run() { 
      System.out.println("Run " + Thread.currentThread().getName() + "-" + name); 
      try { 
       Thread.sleep(time); 
      } catch (InterruptedException ex) { 
       Thread.currentThread().interrupt(); 
      } 
      System.out.println("Finish " + Thread.currentThread().getName() + "-" + name); 
     } 

     @Override 
     public String toString() { 
      return name; 
     } 

    } 
} 

dostaniesz wyjście, które demonstruje wpływ na maximumPoolSize i KeepAliveTime:

init pool size= 0, queue size=0 
Run pool-1-thread-1-1st 
After 1st execute - pool size= 1, queue=[] 
After 2nd execute - pool size= 1, queue=[2nd] 
Run pool-1-thread-2-3d 
After 3d execute - pool size= 2, queue=[2nd] 
Finish pool-1-thread-2-3d 
Run pool-1-thread-2-2nd 
Finish pool-1-thread-2-2nd 
pool size= 1, queue size=0 
Finish pool-1-thread-1-1st