Как закрыть поток из другого, если он не был инициализирован

Я пытаюсь реализовать 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);
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Учитывая код, с которого вы начали, на ум приходят две возможности. Возможно, есть идеи получше, но вот они:

(1) Добавьте дополнительный общедоступный метод в определение вашего анонимного внутреннего класса, который позволяет вам хранить ссылку на внешний поток, который будет отправлен/прерван. После создания обоих потоков сохраните ссылку на каждый из них в другом.

(2) Сохраните ссылку на класс (возможно, тот же класс, который создает и запускает потоки), который будет содержать ссылки на каждый поток. Пусть метод catch вызовет метод в этом запускающем классе, который отправит сообщение (через шаблон слабой связи) или прервет аналог.

Благодаря предложениям! Я применил первый совет, внеся изменения в структуры. Оба анонимных класса относятся к типу Thread, поэтому из них нельзя получить доступ к дополнительному общедоступному методу. Я создал два внутренних класса, которые расширяют Thread, чтобы решить эту проблему, и теперь они работают так, как ожидалось. Я обновил ответ новой реализацией. Еще раз спасибо за ответ!

chaos 12.12.2020 16:01

Другие вопросы по теме