【问题标题】:Java Wait-For-Thread QuestionJava 等待线程问题
【发布时间】:2009-07-30 21:37:44
【问题描述】:

我有一个线程,我需要等待它的结果,像这样:

t1.start();
while (variableModifiedByMyThread == null) {
    /* do nothing */
}
// "t1" set the value of "variableModifiedByMyThread"

上面的代码可以运行,但不是一个很好的解决方案...

这段代码是否在做同样的事情(是否在等待“t1”线程)?

t1.start();
try {
    t1.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
// "t1" thread finished

【问题讨论】:

  • 您的第一个代码示例不是线程安全的。不能保证主线程会在没有锁定/同步的情况下看到对变量“variableModifiedByMyThread”所做的更改。你的主线程可以永远旋转。

标签: java multithreading


【解决方案1】:

前者等待设置变量,后者等待线程死亡。如果变量是在线程终止之前设置的,则几乎没有区别,除了:

  • 以前的“自旋” - 等待线程一直在做某事(检查变量) - 非常浪费!
  • 后者可以被另一个线程中断。

【讨论】:

    【解决方案2】:

    考虑Futures。这个想法是你有一些计算将在“未来某个时间”完成,然后你可以检查它是否已经完成,或者等待它。

    来自 javadoc:

     FutureTask<String> future =
       new FutureTask<String>(new Callable<String>() {
         public String call() {
           return searcher.search(target);
       }});
     executor.execute(future);
    

    【讨论】:

    • 赞成,但要注意的是,您甚至不必将其包装在 FutureTask 中。只需将其提交给 ExecutorService
    【解决方案3】:

    您的第二个代码所做的是观察 t1,然后等待它结束。一旦 t1 死亡,它将再次启动。有关该方法,请参阅 javadoc

    【讨论】:

      【解决方案4】:

      是的,除非您每次有机会检查变量都不会浪费 CPU 周期。这是一种更好的方法。

      这是假设变量仅在t1 完成时才被修改。如果t1 应该修改变量并保持活动状态,这将不起作用。

      顺便说一句,你永远不应该像这样简单地循环等待。您至少应该在循环内调用Thread.yield();否则你可能会在允许任何其他线程运行之前循环多次。

      编辑:实际上,想想看,单元素BlockingQueue 可能是您真正想要的。这听起来像是一个生产者-消费者问题(尤其是如果您不止一次这样做),而 BlockingQueue 就是为这类事情而构建的。

      【讨论】:

        【解决方案5】:

        只要条件成立,您就可以使用 t1.yield() 暂停线程。

        【讨论】:

          【解决方案6】:
          public class Test{
            private final Object lock = new Object();
            private Object var = null;
          
            public void starThreadAndWaitForOutput(){
              Thread t1 = new Thread(new Runnable(){
                public void run(){
                  synchronized(lock){
                    var=new Object();
                    lock.notify();
                  }
                }
              }).start();
          
              synchronized(lock){
                while(var==null)
                  lock.wait();
              }
          
              System.out.println("We have the var and thread 1 is still going!");
            }
          }
          

          【讨论】:

          • 这不太对,您应该防止虚假唤醒。 (有关此信息,请参阅 java.lang.Object.wait javadoc)。结果是你应该说: synchronized (lock) { while (var == null) { lock.wait(); } }
          猜你喜欢
          • 2013-02-03
          • 2017-04-01
          • 2015-07-04
          • 1970-01-01
          • 2011-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多