# Executors.newCachedThreadPool() nicht verstanden



## dmike (2. Jan 2010)

Hi,

wenn ich einen 
	
	
	
	





```
ExecutorService pool = Executors.newCachedThreadPool()
```
anlege

und dann pool.execute(new WorkerThread()); sage was passiert dann?


1a) Wird nur eine Instanz des WorkerThread() gestartet? 
1b) Oder muss ich um rei WorkerThreads im Pool zu besitzen, drei Mal hintereinander pool.execute(new WorkerThread()) aufrufen?

2) Oder werden beliebig viele WorkerThreads gestartet, wie viele entscheidet der Pool.



Eine andere Frage in dem Zusammenhang:

Eine Klasse "PoolManager", die einen Thread startet bzw. einen Pool wie oben gesagt, hat eine start() Methode. Damit soll der Pool gestartet werden. Damit der Pool auch lange genug laufen kann, hab ich in die start() Methode eine Schleife eingebaut. Wenn ich die Klasse starte (mit JUnit), dann geht die CPU Load sofort auf 100% .  


```
/**
     * 
     */
    public void startPool() {
    	try {
    		
    		pool.execute(new WorkerThread());
    		pool.execute(new WorkerThread());
[B]
        	for(;;) {
            	
        	}[/B]
    	} catch (Exception e) {
    		shutdown();
    		throw new RuntimeException(e);
    	}
    }
```


WorkerThread() selbst ist eine Inner-Class des PoolManagers. Die WorkerThreads pollen eine LinkedBlockingQueue  . Die Queue ist leer als was kann die 100% Load machen?



```
private class WorkerThread implements Runnable {
    	private volatile boolean shouldRun = true;

    	WorkerThread() {
    		log.debug("creating worker.");
    	}

        public void run() {
            while (shouldRun) {
                try {
                    MessageTask task = poll(5, MILLISECONDS);
                    
                    if (task == null ) 
                    	continue;
                    
                    task.executeTask();
                    
                    System.out.println("executed");
                
                } catch (Exception e) {
                    shouldRun = false;
                	throw new RuntimeException(e);
                }
            }
        }
    }
```


----------



## Marco13 (2. Jan 2010)

Zum ersten Teil: Man übergibt dort ja keine Threads, sondern Runnables - und für jedes Runnable wird ein neuer Thread erstellt. (Das steht in der Doku zu newCachedThreadPool eigentlich drin...?!)

Die andere Frage... morgen vielleicht


----------



## ThreadPool (2. Jan 2010)

dmike hat gesagt.:


> Hi,
> 
> wenn ich einen
> 
> ...



Dann wird dem Threadpool ein Thread hinzugefügt der dein "Runnable" sprich deinen WorkerThread ausführt. Um drei Jobs [1] zu starten musst du tatsächlich drei mal pool.execute() aufrufen. Der Pool selbst entscheidet, bis auf die Wiedeverwendung eines Threads für den Job, nichts weiter. Des Weiteren kannst dem CachedThreadPool solange Aufgaben übergeben bis dein Speicher platzt. Und diese 100% Auslastung hast du sicher der Endlosschleife zu verdanken.


[1] Du solltest WorkerThread umbenennen da es nicht wirklich ein Thread ist sondern viel mehr ein "Job" der von einem Thread ausgeführt wird. Die Benennung verwirrt sonst, vorallem wenn man später mal wirklich die Klasse Thread erweitert.


----------



## dmike (2. Jan 2010)

Marco13 hat gesagt.:


> (Das steht in der Doku zu newCachedThreadPool eigentlich drin...?!)
> 
> Die andere Frage... morgen vielleicht



Dort steht z.B.

"Creates a thread pool that creates new threads as needed...."

Frage: as needed by whom?  Applikation oder Threadpool?

Das kann man interpretieren wie man will.



ThreadPool hat gesagt.:


> [1] Du solltest WorkerThread umbenennen da es nicht wirklich ein Thread ist, sondern viel mehr ein "Job" der von einem Thread ausgeführt wird. Die Benennung verwirrt sonst, vorallem wenn man später mal wirklich die Klasse Thread erweitert.



Danke für die Erklärung und den Hinweis. Für mich macht ein Runnable nur als Teil eines Threads Sinn, aber hast recht, technisch gesehen ist der Name nicht sauber. Werd ich ändern.

Das mit der Last,  da komme ich immer noch nicht hinter. Dass ein Thread/Runnable Leerlauf hat ist doch gerade Sinne der Aktion. Ich hab den Code soweit, dass beim execute() Aufruf von MessageTask wirklich etwas passiert trotzdem ist da noch genug Leerlauf... und 100% Last

Während der Thread fleißig pollt wartet der Rest des Programms per


```
selector.select( 20 * 1000 );
```

auf irgendeine Event

Die Endlosschleife in JUnit habe ich durch ein Thread.sleep(60*1000) ersetzt.


----------



## ThreadPool (2. Jan 2010)

dmike hat gesagt.:


> Dort steht z.B.
> 
> "Creates a thread pool that creates new threads as needed...."
> 
> ...



Naja, "wie man will" ist übertrieben. Der Threadpool stellt einen Service für seine Verwender bereit nämlich die Jobs die ihm übergeben werden in Threads zu packen und auszuführen. Er erstellt also so viele Threads wie nötig sind um die ganzen Jobs auszuführen die ihm übergeben werden. 

Und zum Rest, dann liegt es vermutlich an dem "polling" welches du innerhalb eines Runnables betreibst, das Runnable wird zwar für höchstens 5 ms suspended während des poll() am Queue aber wenn es mehrere solcher Jobs gibt und die alle ständig die while-Schleife durchackern wird die Auslastung dementsprechend hoch sein.


----------

