Как мне получить возвращаемое значение из метода, управляемого внутренним потоком, в Java?

#java #multithreading

#java #многопоточность

Вопрос:

Как мне назначить Status с CallMe() помощью isFinish() , чтобы возвращаемое значение было истинным?

 public static boolean isFinish ()
{    
  boolean Status = false;
  new Thread(new Runnable()
  {
    public void run()
    {
      /* This shell return true or false 
       * How do you keep it in Status
       */
      CallMe(); 
    }
  }).start();

  /* How can i get the true or false exactly from CallMe? here */
  return Status;
}

public static boolean CallMe()
{
  /* some heavy loads ... */
  return true;
}
  

Комментарии:

1. Зачем вообще использовать поток? Start() создаст отдельный поток выполнения, и в этот момент isFinish продолжит его выполнение.

Ответ №1:

Есть два способа сделать это. Первый — использовать будущий результат вычисления, а другой — иметь общую переменную. Я думаю, что первый метод намного чище второго, но иногда вам также нужно передавать значения в поток.

  • Используя RunnableFuture .

FutureTask реализует RunnableFuture . Итак, вы создаете эту задачу, которая после выполнения будет иметь значение.

 RunnableFuture f = new FutureTask(new Callable<Boolean>() {
  // implement call
});
// start the thread to execute it (you may also use an Executor)
new Thread(f).start();
// get the result
f.get();
  
  • Использование класса holder

Вы создаете класс, содержащий значение, и предоставляете ссылку на этот класс. Вы можете создать свой собственный класс или просто использовать AtomicReference . Под классом holder я подразумеваю класс, который имеет общедоступный изменяемый атрибут.

 // create the shared variable
final AtomicBoolean b = new AtomicBoolean();
// create your thread
Thread t = new Thread(new Runnable() {
  public void run() {
    // you can use b in here
  }
});
t.start();
// wait for the thread
t.join();
b.get();
  

Комментарии:

1. 1, как два метода, действительно спасибо. Мне нужно было иметь полнодуплексный режим, который дает мне наилучшее направление.

2. Спасибо! Мне это было нужно для моего университетского проекта, вы очень помогли.

Ответ №2:

Вы переписываете код для использования Callable<Boolean> и получаете a Future при запуске Runnable .

Фьючерсы позволяют запускающему потоку правильно проверять готовность значения и считывать его асинхронно. Вы могли бы выполнить кодирование вручную, но поскольку Future теперь оно является частью стандартных библиотек JVM, зачем вам это (вне класса программирования)?

Ответ №3:

Работая с необработанными потоками, вы могли бы реализовать Runnable с именованным типом и сохранить в нем значение.

 class MyRunnable implements Runnable {
   boolean status;

   public void run() {
      ...
   }
}
  

Однако, если вы работаете с другим потоком, вам придется каким-то образом синхронизировать.

Было бы проще использовать инструменты более высокого уровня, предоставляемые иерархией java.util.concurrent. Вы можете отправить вызываемый объект исполнителю и получить будущее. Вы можете спросить будущее, сделано ли это, и получить результат. Здесь есть руководство по Oracle.