L'approccio nella risposta di Kylar è corretto. Utilizzare le classi executor fornite dalle librerie di classi Java piuttosto che implementare il thread pooling da zero (male).
Ma ho pensato che potrebbe essere utile discutere il codice nella domanda e perché non funziona. (Ho compilato alcune delle parti che hai lasciato fuori nel miglior modo possibile ...)
public class MyThread extends Thread {
private static int counter;
public MyThread(String fileName, Object lock) {
// Save parameters in instance variables
}
public void run() {
// Do stuff with instance variables
counter--;
}
public static void main(String[] args) {
// ...
for (final File filename : folder.listFiles()) {
Object lock1 = new Object();
new MyThread(filename, lock1).start();
counter++;
while (counter > 5);
}
// ...
}
}
OK, così che cosa è sbagliato in questo? Perché non funziona?
Bene, il primo problema è che in main
si sta leggendo e scrivendo counter
senza eseguire alcuna sincronizzazione. Presumo che venga aggiornato anche dai thread di lavoro: il codice non ha senso altrimenti. Ciò significa che ci sono buone probabilità che i thread principali non vedano il risultato degli aggiornamenti fatti dai thread figli. In altre parole, while (counter > 5);
potrebbe essere un ciclo infinito. (In realtà, questo è abbastanza probabile. Il compilatore JIT è permesso di generare il codice in cui il counter > 5
mette alla prova semplicemente il valore di counter
lasciato in un registro dopo la counter++;
precedente dichiarazione.
Il secondo problema è che il ciclo while (counter > 5);
è incredibilmente dispendioso di risorse. Stai dicendo alla JVM di eseguire il polling di una variabile ... e questo farà potenzialmente MILIARDI di volte al secondo ... eseguendo un processore (core) completamente fuori. Non dovresti farlo. implementando questo tipo di cose usando le primitive di basso livello, dovresti usare i metodi Java Object.wait()
e Object.notify()
, ad esempio il thread principale attende e ogni thread di lavoro lo notifica.
fonte
2011-12-28 04:09:38
+1. Non ha senso reinventare la ruota. Penso che tu intenda ThreadPoolExecutor, però. Non c'è ExecutorPool in J2SE che io conosca. –
Jdk5 in poi ci sono molte classi inbuit per la gestione dei thread.Come suggerito da Kylar, è meglio usare Executorpool – kosa
Sì, intendevo in realtà ExecutorService. Risolto e aggiunto un codice sorgente GREY SUPER per darti il succo. – Kylar