Например, мне нужно всегда запускать 100 потоков, чтобы выполнить какое-то действие. У меня есть класс, который называется ThreadsWorker, который ищет количество потоков и запускает отсутствующие потоки, если некоторые предыдущие завершены. Итак, это таблица, описывающая ситуацию:
1 second: 100 threads
2 second: 92 threads (ThreadsWorker generates new 8 threads)
3 second: 100 theads
4 second: 72 threads (ThreadsWorker generates 28 threads)
И так далее. Мои потоки являются анонимными вызовами (просто new Thread(new Runnable(...)).start()), потому что я не знаю, как правильно сохранить их в массив Threads[], потому что, хотя ThreadsWorker сохранит threads[i] = new Threads(), некоторые потоки могут быть завершены, и тогда будет некоторая коллизия с индексами массива.
Из-за анонимных вызовов я теперь использую переменную threadsCount и увеличиваю ее в начале тела потока и уменьшаю в конце тела потока (используя synchronized). Хорошо, это работает правильно, и мой единственный способ - использовать цикл while(), который проверяет, threadsCount == 0 ли, когда прогресс завершен.
Я думаю, что это в стиле C, но не в стиле Java :) Итак, вы можете помочь мне сделать это в стиле Java?
Ответ 1 · рейтинг 6 · Michael Brewer-Davis
Если ваша цель состоит в том, чтобы просто иметь 100 активных потоков, я предлагаю взглянуть на Java пулы потоков (и Исполнители в более общем смысле).
Мне неясно, хотите ли вы сохранить все 100 потоков или дождаться их завершения. Ваш вопрос ссылается на оба (ThreadsWorker порождает 28 новых потоков, threadsCount == 0), и они кажутся противоречивыми.
Ответ 2 · рейтинг 5 · squawknull
Поместите все потоки в массив или коллекцию.
Затем прокрутите коллекцию, вызывая Thread.join() для каждого. Когда этот цикл завершается, все потоки выполняются.
ArrayList threads = new ArrayList();
for (int i = 0; i < 5; i++) {
Thread t = new AweseomeThread();
t.start();
threads.add(t);
}
for (Thread t : threads) {
t.join();
}
Вам также понадобится обработка исключений (например, InterruptedException). Но я оставлю это как упражнение для читателя... :)
Ответ 3 · рейтинг 3 · store88
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html
Вы можете попробовать класс CountDownLatch jdk API
private CountDownLatch latch;
private static class SimpleThread extends Thread {
public void run() {
latch.countDown();
}
}
public static void main(String[] args) {
int threadcount = 10;
latch = new CountDownLatch(threadcount);
for (int i = 0; i < 10; i++) {
Thread t = new SimpleThread();
t.start();
}
// waiting threads all finished
latch.await();
}
Получить количество потоков из атрибута latch класса Main.
Ответ 4 · рейтинг 2 · richs
Я полагаю, вы пытаетесь заставить ThreadWorker отправлять новые потоки для всех завершенных потоков.
Я бы использовал BlockingQueue, к которому добавляются потоки (ваши Runnable(s)) по завершении. ThreadWorker будет ждать завершения потока, а затем запустит новый поток.
public class YourRunnable implements Runnable {
private final BlockingQueue<YourRunnable> queue;
public YourRunnable(BlockingQueue<YourRunnable> queue){
this.queue = queue;
}
public void run{
// Your Code...
// Finished Processing
queue.add(this);
}
}
public class ThreadWorkder implements Runnable {
private final BlockingQueue<YourRunnable> queue;
ThreadWorker(BlockingQueue<YourRunnable> queue){
this.queue = queue;
}
public void run{
while(queue.take()){
(new Thread(new YourRunnable(queue))).start();
}
}
// general main method
public static void main(String [] args){
BlockingQueue<YourRunnable> queue = new LinkedBlockingQueue<YourRunnable>();
ThreadWorker worker = new ThreadWorker(queue);
Thread(worker).start();
for (int i = 0; i < 100; i++){
(new Thread(new YourRunnable(queue))).start();
}
}
}
Ответ 5 · рейтинг 1 · squawknull
Используйте коллекцию вместо массива. Когда потоки завершатся, пусть они удалятся из массива. Что-то вроде этого:
public class Foo {
Vector<Thread> threads = new Vector<Thread>(); //Vector is threadsafe
public ensureThreadCount(int count) {
while (threads.size() < count) {
Thread t = new AweseomeThread(threads);
threads.add(t);
t.start();
}
}
}
public class AwesomeThread {
Collection threads;
public AwesomeThread(Collection threads) {
this.threads = threads;
}
public void run() {
try {
// do stuff
} catch (Throwable t) {
} finally {
threads.remove(this);
}
}
}
Затем пусть ваш воркер просто вызовет Foo.ensureThreadCount().