Мой M(Non)WE выглядит следующим образом:
public class SOQuestion1 {
public static void main(String[] args) {
ProducerThread producerThread1 = new ProducerThread();
ProducerThread producerThread2 = new ProducerThread();
ControllerThread1 controllerThread1 =
new ControllerThread1(producerThread1);
controllerThread1.start();
ControllerThread2 controllerThread2 =
new ControllerThread2(producerThread2);
controllerThread2.start();
}
}
class ProducerThread extends Thread {
@Override
public void run() {
while (true);
}
}
class ControllerThread1 extends Thread {
private final ProducerThread producerThread;
ControllerThread1(ProducerThread producerThread) {
this.producerThread = producerThread;
}
@Override
public void run() {
producerThread.start();
System.out.println("Started ControllerThread1.");
try {
producerThread.join(2000);
Thread.sleep(2000);
producerThread.interrupt();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Joined ControllerThread1.");
}
}
class ControllerThread2 extends Thread {
private final ProducerThread producerThread;
ControllerThread2(ProducerThread producerThread) {
this.producerThread = producerThread;
}
@Override
public void run() {
producerThread.start();
System.out.println("Started ControllerThread2.");
try {
Thread.sleep(2000);
producerThread.interrupt();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Joined ControllerThread2.");
}
}
Он выводит:
Started ControllerThread1.
Started ControllerThread2.
Joined ControllerThread2.
Joined ControllerThread1.
... и потоки-производители продолжают работать.
Однако здесь есть ограничение: поскольку мой будущий поток-производитель будет загружать данные из Интернета, неизвестно, как быстро ответит сервер, и поэтому я не могу полагаться на флаги в потоках-производителях.
Есть ли способ решить эту проблему без использования флагов продолжения потока?
По сути, я хотел сказать, что логический флаг в бесконечном цикле потока невозможен. Мой поток-производитель вызовет метод, который в худшем случае блокируется на неопределенный срок.
Я бы использовал неблокирующий ввод-вывод для потока-производителя, таким образом вы можете использовать любую синхронизацию потоков, которую вы предпочитаете.
На самом деле это может не быть решением вашего требования «Я не могу полагаться на флаги в потоках производителя», но для проблемы в вашем примере, когда ваш поток производителя продолжает работать, если вы хотите прервать поток, вам нужно разрешить поток быть прерванным. вместо while(true) должно быть while(!Thread.isInterrupted())
@BIBOOnation Хороший вариант, но он не соответствует моим требованиям.
@cyberbrain Не могли бы вы уточнить, что вы имеете в виду под неблокирующим вводом-выводом? Как насчет ответа?
К сожалению, сейчас я не могу дать вам готовый ответ, так как сам не часто им пользуюсь. Но я имел в виду использование вызовов в пакете java.nio вместо java.io (если вы используете стандартную Java) или использование таких фреймворков, как Spring WebFlux.
Простите за мое плохое понимание, но вы спрашиваете, как прекратить действие ProducerThread после того, как ControllerThread1 и ControllerThread2 завершились?
@Абра, нет плохого понимания. Вы поняли это совершенно правильно.
Если вы загружаете через HTTP(S), вы можете рассмотреть возможность использования java.net.http.HttpClient, метод send которого можно прервать.




Очень просто. Создайте поток демона ProducerThreads s. По умолчанию это не так. В приведенном ниже коде я просто добавил две строки, которые явно устанавливают созданные ProducerThread как потоки демона.
public class SOQuestion1 {
public static void main(String[] args) {
ProducerThread producerThread1 = new ProducerThread();
producerThread1.setDaemon(true); // ADDED
ProducerThread producerThread2 = new ProducerThread();
producerThread2.setDaemon(true); // ADDED
ControllerThread1 controllerThread1 = new ControllerThread1(producerThread1);
controllerThread1.start();
ControllerThread2 controllerThread2 = new ControllerThread2(producerThread2);
controllerThread2.start();
}
}
class ProducerThread extends Thread {
@Override
public void run() {
while (true)
;
}
}
class ControllerThread1 extends Thread {
private final ProducerThread producerThread;
ControllerThread1(ProducerThread producerThread) {
this.producerThread = producerThread;
}
@Override
public void run() {
producerThread.start();
System.out.println("Started ControllerThread1.");
try {
producerThread.join(2000);
Thread.sleep(2000);
producerThread.interrupt();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Joined ControllerThread1.");
}
}
class ControllerThread2 extends Thread {
private final ProducerThread producerThread;
ControllerThread2(ProducerThread producerThread) {
this.producerThread = producerThread;
}
@Override
public void run() {
producerThread.start();
System.out.println("Started ControllerThread2.");
try {
Thread.sleep(2000);
producerThread.interrupt();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Joined ControllerThread2.");
}
}
Вот результат, когда я запускаю приведенный выше код:
Started ControllerThread1.
Started ControllerThread2.
Joined ControllerThread2.
Joined ControllerThread1.
После отображения последней строки вывода JVM завершает работу.
Именно то, что я искал, спасибо!
Что именно вы подразумеваете под «флагами продолжения потока»? Это встроенный механизм Java или что-то, что вы создаете в своем коде?