Как реализовать простую поточную обработку с постоянным числом рабочих потоков

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

50
задан Raedwald 29 April 2014 в 04:41
поделиться

6 ответов

Я думаю, что Executors.newFixedThreadPool соответствует Вашим требованиям. Существует много различных способов использовать получающийся ExecutorService, в зависимости от того, хотите ли Вы результат, возвращенный к основному потоку, или является ли задача полностью автономной, и есть ли у Вас набор задач работать впереди, или ставятся ли задачи в очередь в ответ на некоторое событие.

  Collection<YourTask> tasks = new ArrayList<YourTask>();
  YourTask yt1 = new YourTask();
  ...
  tasks.add(yt1);
  ...
  ExecutorService exec = Executors.newFixedThreadPool(5);
  List<Future<YourResultType>> results = exec.invokeAll(tasks);

, С другой стороны, если у Вас есть новая асинхронная задача работать в ответ на некоторое событие, Вы, вероятно, просто хотите использовать ExecutorService, простой execute(Runnable) метод.

56
ответ дан Ravindra babu 7 November 2019 в 10:55
поделиться
/* Get an executor service that will run a maximum of 5 threads at a time: */
ExecutorService exec = Executors.newFixedThreadPool(5);
/* For all the 100 tasks to be done altogether... */
for (int i = 0; i < 100; i++) {
    /* ...execute the task to run concurrently as a runnable: */
    exec.execute(new Runnable() {
        public void run() {
            /* do the work to be done in its own thread */
            System.out.println("Running in: " + Thread.currentThread());
        }
    });
}
/* Tell the executor that after these 100 steps above, we will be done: */
exec.shutdown();
try {
    /* The tasks are now running concurrently. We wait until all work is done, 
     * with a timeout of 50 seconds: */
    boolean b = exec.awaitTermination(50, TimeUnit.SECONDS);
    /* If the execution timed out, false is returned: */
    System.out.println("All done: " + b);
} catch (InterruptedException e) { e.printStackTrace(); }
25
ответ дан Fabian Steeg 7 November 2019 в 10:55
поделиться

Executors.newFixedThreadPool (интервал)

Executor executor = Executors.newFixedThreadPool(n);

Runnable runnable = new Runnable() {
 public void run() {
  // do your thing here
 }
}

executor.execute(runnable);
7
ответ дан Ravindra babu 7 November 2019 в 10:55
поделиться

Используйте платформу Исполнителя; а именно, newFixedThreadPool (N)

2
ответ дан Ravindra babu 7 November 2019 в 10:55
поделиться

Если Вы хотите к самокрутке:

private static final int MAX_WORKERS = n;
private List<Worker> workers = new ArrayList<Worker>(MAX_WORKERS);

private boolean roomLeft() {
    synchronized (workers) {
        return (workers.size() < MAX_WORKERS);
    }
}

private void addWorker() {
    synchronized (workers) {
        workers.add(new Worker(this));
    }
}

public void removeWorker(Worker worker) {
    synchronized (workers) {
        workers.remove(worker);
    }
}

public Example() {
    while (true) {
        if (roomLeft()) {
            addWorker();
        } 
    }
}

, Где Рабочий является Вашим классом, который расширяет Поток. Каждый рабочий назовет removeWorker метод этого класса, передавая себя в в качестве параметра, когда он закончил делать, это - вещь.

После этих слов платформа Исполнителя выглядит намного лучше.

Редактирование: Кто-либо хочет объяснить, почему это настолько плохо, вместо просто downmodding это?

0
ответ дан rjohnston 7 November 2019 в 10:55
поделиться

Как другие здесь упомянули, Ваш лучший выбор состоит в том, чтобы сделать пул потоков с эти Исполнители класс:

Однако, если Вы хотите к самокрутке, этот код должен дать Вам общее представление, как продолжить двигаться. В основном просто добавьте каждый новый поток к группе потока и удостоверьтесь, что у Вас никогда нет больше, чем активные потоки N в группе:

Task[] tasks = getTasks(); // array of tasks to complete
ThreadGroup group = new ThreadGroup();
int i=0;
while( i<tasks.length || group.activeCount()>0 ) {
    if( group.activeCount()<N && i<tasks.length ) {
        new TaskThread(group, tasks[i]).start();
        i++;
    } else {
        Thread.sleep(100);
    }
}
0
ответ дан Ravindra babu 7 November 2019 в 10:55
поделиться