Я пытаюсь реализовать Linux pipe operator |
с помощью java. Основная идея заключается в назначении связанных PipedInputStream
и PipeOutputStream
двум командам, и они могут выполнять свои действия одновременно.
Реализация выглядит следующим образом:
PipedOutputStream pOutputStream = new PipedOutputStream();
PipedInputStream pInputStream = new PipedInputStream();
pOutputStream.connect(pInputStream);
Thread thread1, thread2;
thread1 = new Thread(){
public void run() {
try {
new Call(pipe.cmd1).eval(CommandHandler.this, inputStream, pOutputStream);
pOutputStream.close();
} catch (Exception e) {
thread2.interrupt(); // cannot do this as it may not have been initialized
}
}
};
thread2 = new Thread() {
public void run() {
try{
new Pipe(pipe.cmd2).eval(CommandHandler.this, pInputStream, outputStream);
// pInputStream.close();
} catch (Exception e) {
// kill the first thread when the second one raises an exception
thread1.interrupt();
throw e;
}
}
};
thread1.start();
thread2.start();
// waiting for the two threads to die before carry on
thread2.join();
thread1.join();
Я хотел бы прервать второй поток, когда первый вызовет исключение, как я сделал в thread2 catch
. Проблема в том, что thread2
назначается последним, поэтому я не могу получить к нему доступ в thread1. Я попытался инициализировать thread1&2
нулевыми значениями, но тогда они должны быть окончательными, поскольку они находятся в охватывающей области.
Простите, если глупый вопрос, я только начинаю изучать многопоточность в java.
** ОБНОВЛЯТЬ **
Благодаря предложениям Фила. Я заменил два анонимных внутренних класса на два внутренних класса, расширяющих Thread
.
class Thread1 extends Thread{
public Thread counterThread;
public void run() {
try {
new Call(pipe.cmd1).eval(CommandHandler.this, inputStream, pOutputStream);
pOutputStream.close();
} catch (Exception e) {
// kill thread 2
if (counterThread != null) counterThread.interrupt();
}
}
public void setThread(Thread thread) {
counterThread = thread;
}
};
class Thread2 extends Thread {
public Thread counterThread;
public void run() {
try{
new Pipe(pipe.cmd2).eval(CommandHandler.this, pInputStream, outputStream);
// pInputStream.close();
} catch (Exception e) {
// kill the first thread when the second one raises an exception
if (counterThread != null) counterThread.interrupt();
throw e;
}
}
public void setThread(Thread thread) {
counterThread = thread;
}
};
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
thread1.setThread(thread2);
thread2.setThread(thread1);
Учитывая код, с которого вы начали, на ум приходят две возможности. Возможно, есть идеи получше, но вот они:
(1) Добавьте дополнительный общедоступный метод в определение вашего анонимного внутреннего класса, который позволяет вам хранить ссылку на внешний поток, который будет отправлен/прерван. После создания обоих потоков сохраните ссылку на каждый из них в другом.
(2) Сохраните ссылку на класс (возможно, тот же класс, который создает и запускает потоки), который будет содержать ссылки на каждый поток. Пусть метод catch
вызовет метод в этом запускающем классе, который отправит сообщение (через шаблон слабой связи) или прервет аналог.
Благодаря предложениям! Я применил первый совет, внеся изменения в структуры. Оба анонимных класса относятся к типу
Thread
, поэтому из них нельзя получить доступ к дополнительному общедоступному методу. Я создал два внутренних класса, которые расширяютThread
, чтобы решить эту проблему, и теперь они работают так, как ожидалось. Я обновил ответ новой реализацией. Еще раз спасибо за ответ!