Тип вопроса: Учебник по Java Threading
-
03-07-2019 - |
Вопрос
Я довольно наивен, когда дело касается мира Java Threading и Concurrency.В настоящее время я пытаюсь учиться.Я привел простой пример, чтобы попытаться понять, как работает параллелизм.
Вот мой код:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadedService {
private ExecutorService exec;
/**
* @param delegate
* @param poolSize
*/
public ThreadedService(int poolSize) {
if (poolSize < 1) {
this.exec = Executors.newCachedThreadPool();
} else {
this.exec = Executors.newFixedThreadPool(poolSize);
}
}
public void add(final String str) {
exec.execute(new Runnable() {
public void run() {
System.out.println(str);
}
});
}
public static void main(String args[]) {
ThreadedService t = new ThreadedService(25);
for (int i = 0; i < 100; i++) {
t.add("ADD: " + i);
}
}
}
Что мне нужно сделать, чтобы код выводил числа от 0 до 99 в последовательном порядке?
Решение
Пулы потоков обычно используются для операций, которые не требуют синхронизация или очень параллельный.
Последовательная печать чисел 0–99 не является параллельной проблемой и требует синхронизации потоков, чтобы избежать нарушения порядка печати.
Рекомендую взглянуть на Урок Java-параллелизма чтобы получить представление о параллелизме в Java.
Другие советы
Идея потоков заключается не в том, чтобы делать что-то последовательно.
Для координации вам понадобится какое-то общее состояние.В этом примере добавление полей экземпляра во внешний класс будет работать.Удалите параметр из доп.Добавьте объект блокировки и счетчик.Возьмите замок, увеличьте число, напечатайте число, увеличьте число, отпустите число.
Самое простое решение вашей проблемы — использовать размер ThreadPool, равный 1.Однако на самом деле это не та проблема, для решения которой можно было бы использовать потоки.
Чтобы расширить, если вы создадите своего исполнителя с помощью:
this.exec = Executors.newSingleThreadExecutor();
тогда все ваши потоки будут запланированы и выполнены в том порядке, в котором они были отправлены на выполнение.Есть несколько сценариев, в которых это логично, но в большинстве случаев потоки — неправильный инструмент для решения этой проблемы.
Подобные вещи имеет смысл делать, когда вам нужно выполнить задачу в другом потоке — возможно, это занимает много времени, и вы не хотите блокировать поток графического интерфейса — но вам это не нужно или не нужно Я не хочу, чтобы отправленные задачи выполнялись одновременно.
Проблема по определению не подходит для потоков.Потоки запускаются независимо, и на самом деле не существует способа предсказать, какой поток запустится первым.
Если вы хотите изменить свой код для последовательного запуска, измените add на:
public void add(final String str) {
System.out.println(str);
}
Вы не используете потоки (по крайней мере, свои), и все происходит последовательно.