Подход в ответе Кайлара правильный.Используйте классы executor, предоставляемые библиотеками классов Java, вместо того, чтобы реализовывать пул потоков с нуля (плохо).
Но я подумал, что было бы полезно обсудить код в вашем вопросе и почему он не 'т работа.(Я заполнил некоторые части, которые вы пропустили как можно лучше ...)
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);
}
// ...
}
}
ОК, так что же с этим не так?Почему это не работает?
Ну, первая проблема в том, что в main
вы читаете и пишете counter
без какой-либо синхронизации.Я предполагаю, что он также обновляется рабочими потоками - иначе код не имеет смысла.Это означает, что есть большая вероятность, что основные потоки не увидят результат обновлений, сделанных дочерними потоками.Другими словами, while (counter > 5);
может быть бесконечным циклом.(На самом деле, это довольно вероятно. JIT-компилятору разрешено генерировать код, в котором counter > 5
просто проверяет значение counter
, оставленное в регистре после предыдущего оператора counter++;
.
Вторая проблема заключается в том, что ваш цикл while (counter > 5);
невероятно бесполезен. Вы говорите JVM опрашивать переменную ... и она будет делать это потенциально МИЛЛИАРДЫ раз в секунду ... запустив один процессор (ядро).Вы не должны этого делать. Если вы собираетесь реализовывать подобные вещи с использованием низкоуровневых примитивов, вы должны использовать Java Object.wait()
и Object.notify()
методы, например, основной поток ожидает, и каждый рабочий поток уведомляет.