2015-06-20 5 views
6

Sono nuovo in questa programmazione concorrente in java e ho elaborato i seguenti scenari in cui mi sto confondendo su quale utilizzare quando.

Scenario 1: Nel seguente codice che stava cercando di eseguire i thread chiamando .start() sulla classe GPSService che è un'implementazione Runnable.Quale è la differenza tra executeService e thread.run nell'esecuzione di thread contemporaneamente in Java?

int clientNumber = 0; 
ServerSocket listener = new ServerSocket(port); 

while (true) { 
      new GPSService(listener.accept(), clientNumber++, serverUrl).start(); 
} 

Scenario 2: Nel seguente codice che stava cercando di eseguire i thread utilizzando classe ExecutorService come mostrato

int clientNumber = 0; 
ServerSocket listener = new ServerSocket(port); 
while(true) { 
     ExecutorService executor = Executors.newSingleThreadExecutor(); 
     executor.execute(new GPSService(listener.accept(), client++, serverUrl)); 

     executor.shutdown(); 
     while (!executor.awaitTermination(1, TimeUnit.SECONDS)) { 
      // Threads are still running 
      System.out.println("Thread is still running"); 
     } 
     // All threads are completed 
     System.out.println("\nThread completed it's execution and terminated successfully\n");    
} 

Le mie domande sono
che è la pratica migliore per invocare un filo in programmazione concorrente?
Quale sarà il risultato (guai) Mi ritroverò quando uso il primo o il secondo?
Nota: Ho riscontrato un problema con il primo scenario in cui il programma viene sospeso dopo alcuni giorni. Quindi, il problema è relativo/atteso quando utilizzo il primo metodo?
Qualsiasi risposta valida/utile sarà apprezzata :) Grazie

+0

possibile duplicato del [pool di thread vs Spawning thread] (http://stackoverflow.com/questions/2049948/thread-pool-vs-thread -spawning) –

+0

@NarendraPathai Sono più specifico della mia domanda, se sì, come puoi contrassegnarlo come duplicato ??? –

+0

@NarendraPathai Ho appena menzionato l'appeso solo per chiarire se FirstScenario ha la possibilità di causare tali problemi. Per tua comprensione, non ho chiesto la soluzione per quel problema sospensivo. E grazie per il vostro riferimento –

risposta

3

Non ci sono grandi differenze nei due scenari che hai pubblicato, tranne che dalla gestione della terminazione del thread in Scenario2; crei sempre un nuovo thread per ogni richiesta in arrivo. Se si desidera utilizzare ThreadPool, il mio consiglio è di non crearne uno per ogni richiesta, ma di crearne uno per ciascun server e riutilizzare i thread. Qualcosa di simile:

public class YourClass { 

//in init method or constructor 
ExecutorService executor = Executors....;// choose from newCachedThreadPool() or newFixedThreadPool(int nThreads) or some custom option 


int clientNumber = 0; 
ServerSocket listener = new ServerSocket(port); 
while(true) { 

    executor.execute(new GPSService(listener.accept(), client++, serverUrl)); 

} 

Ciò consentirà di utilizzare un pool di thread e di controllare il numero di thread da utilizzare per il server. Se vuoi usare un Executor questo è il modo migliore per andare.

Con un pool di server è necessario decidere quanti thread ci sono nel pool; hai diverse scelte ma puoi iniziare o con un numero fisso o thread o con un pool che tenta di usare un thread non occupato e se tutti i thread sono occupati ne crea uno nuovo (newCachedThreadPool()). Il numero di thread da allocare dipende da molti fattori: il numero di richieste concomitanti e le durate. Quanto più il tuo side code del server richiede più tempo hai bisogno di thread aggiuntivi. Se il tuo side code del server è molto più veloce, ci sono possibilità molto alte che il pool possa riciclare i thread già allocati (poiché le richieste non arrivano tutte nello stesso esatto istante).

Si supponga ad esempio di avere 10 richieste in un secondo e ogni richiesta dura 0,2 secondi; se la richiesta arriva a 0, 0,1, 0,2, 0,3, 0,4, 0,5, .. parte del secondo (ad esempio 23/06/2015 7: 16: 00: 00, 23/06/2015 7:16:00: 01, 23/06/2015 7: 16: 00: 02) sono necessari solo tre thread poiché la richiesta proveniente da 0.3 può essere eseguita dal thread che server la prima richiesta (quella a 0), e così via (la richiesta al tempo 0.4 può riutilizzare il thread utilizzato per la richiesta che è arrivata a 0.1). Dieci richieste gestite da tre thread.

Vi raccomando (se non l'avete già fatto) di leggere Concorrenza Java in pratica (L'esecuzione dell'esecuzione è il capitolo 6); che è un eccellente libro su come creare un'applicazione concorrente in Java.

+0

Quindi, se uso newCachedThreadPool() o newFixedThreadPool (int nThreads), dato che ottengo i dati ogni quattro secondi da centinaia di client, non mi fermerò con qualche problema se non lo faccio utilizzare un singolo thread per ogni cliente? –

+1

Nessun problema se riesci a ridimensionare il pool correttamente, con newCachedThreadPool() non hai nemmeno messo un limite superiore sul numero di filo – Giovanni

1

da Oracle documentation da Executors

public static ExecutorService newCachedThreadPool() 

crea un pool filo che crea nuovi thread se necessario, ma sarà riutilizzare fili già costruiti quando sono disponibili. Questi pool in genere migliorano le prestazioni dei programmi che eseguono molte attività asincrone di breve durata.

Le chiamate da eseguire riutilizzeranno i thread costruiti in precedenza, se disponibili. Se nessun thread esistente è disponibile, un nuovo thread verrà creato e aggiunto al pool. I thread che non sono stati usati per sessanta secondi sono terminati e rimossi dalla cache.

Pertanto, un pool che rimane inattivo per un tempo sufficiente non consuma risorse. Si noti che pool con proprietà simili ma dettagli diversi (ad esempio, parametri di timeout) possono essere creati utilizzando i costruttori ThreadPoolExecutor.

public static ExecutorService newFixedThreadPool(int nThreads) 

crea un pool filo che riutilizza un numero fisso di thread operano fuori una coda illimitata condivisa. In qualsiasi momento, al massimo i thread nThreads saranno attività di elaborazione attive. Se vengono inoltrate attività aggiuntive quando tutti i thread sono attivi, attenderanno in coda fino a quando un thread non sarà disponibile.

Se un thread si interrompe a causa di un errore durante l'esecuzione prima dello spegnimento, ne verrà sostituito uno nuovo se necessario per eseguire le attività successive. I thread nel pool esisteranno fino a quando non verranno arrestati esplicitamente.

@Giovanni sta dicendo che don' necessario fornire il numero di thread da newCachedThreadPool a differenza newFixedThreadPool(), in cui devi passare il massimo tappo sul numero di thread nel ThreadPool.

Ma tra questi due, newFixedThreadPool() è preferito. newCachedThread Pool potrebbe causare perdite e si potrebbe raggiungere il numero massimo di thread disponibili a causa della natura illimitata. Alcune persone lo considerano un male.

Dai un'occhiata alla relativa domanda SE:

Why is an ExecutorService created via newCachedThreadPool evil?

+0

Quando usi newFixedThreadPool() come puoi determinare quale numero usare per i thread. – Jesse

+0

Inizia con Runtime.getRuntime(). AvailableProcessors() –