【问题标题】:How to notify another thread如何通知另一个线程
【发布时间】:2012-12-29 01:47:23
【问题描述】:

我想知道如何通知另一个线程的最佳方式。比如我有一个后台线程:

public void StartBackgroundThread(){
new Thread(new Runnable() {         
        @Override
        public void run() {
            //Do something big...
            //THEN HOW TO NOTIFY MAIN THREAD?
        }
    }).start();
}

当它完成时它必须通知主线程?如果有人知道如何做到这一点的最佳方法,我将不胜感激!

【问题讨论】:

  • 考虑阅读以下内容:javaworld.com/javaworld/jw-07-2002/jw-0703-java101.html 它涵盖了通知。 (特别是第 7 页)
  • 主线程在做什么,而第二个线程在做“大事”?它只会在第二个线程上等待吗?如果是这样,你为什么需要第二个线程呢?如果没有,你需要多说一下它会做什么。
  • 主线程将渲染GUI,例如...

标签: java multithreading


【解决方案1】:

你不能“通知主线程”。

最好的方法是使用ExecutorService,例如:

 import java.util.concurrent.*;

 // in main thread
 ExecutorService executorService = Executors.newSingleThreadExecutor();

 Future<?> future = executorService.submit(new Runnable() {         
    @Override
    public void run() {
        //Do something big...
    }
});

future.get(); // blocks until the Runnable finishes

这些类是专门为处理异步操作而编写的,里面的所有代码都已经为你编写好了,防弹的。

编辑

如果您不想在等待时阻塞主线程,请在另一个线程中等待:

 final Future<?> future = executorService.submit(new Runnable() {         
    @Override
    public void run() {
        //Do something big...
    }
});

new Thread(new Runnable() {         
    @Override
    public void run() {
        future.get(); // blocks until the other Runnable finishes
        // Do something after the other runnable completes
    }
}).start();

【讨论】:

  • 你能告诉我为什么我们不能通知主线程吗?我有兴趣了解
  • 但是如果我想在主线程中的其他可运行对象完成后做些什么呢?
  • 将我的答案代码中的注释// Do something after the other runnable completes替换为您需要做的任何事情
【解决方案2】:

完全根据您的问题,您可以这样做:

public class test
{
  Object syncObj = new Object();

  public static void main(String args[])
  {
    new test();
  }

  public test()
  {
    startBackgroundThread();

    System.out.println("Main thread waiting...");
    try
    {
      synchronized(syncObj)
      {
        syncObj.wait();
      }
    }
    catch(InterruptedException ie) { }
    System.out.println("Main thread exiting...");
  }

  public void startBackgroundThread()
  {
    (new Thread(new Runnable()
    {
      @Override
      public void run()
      {
        //Do something big...
        System.out.println("Background Thread doing something big...");
        //THEN HOW TO NOTIFY MAIN THREAD?
        synchronized(syncObj)
        {
          System.out.println("Background Thread notifing...");
      syncObj.notify();
        }
        System.out.println("Background Thread exiting...");
      }
    })).start();
  }
}

看看这个输出

PS C:\Users\java> javac test.java
PS C:\Users\java> java test
Main thread waiting...
Background Thread doing something big...
Background Thread notifing...
Background Thread exiting...
Main thread exiting...

【讨论】:

    【解决方案3】:

    典型的答案是BlockingQueueBackgroundThread(通常称为生产者)和MainThread(通常称为消费者)共享队列的单个实例(可能在实例化时得到它)。 BackgroundThread 每次有新消息时调用 queue.put(message)MainThread 调用 'queue.take()which will block until there's a message to receive. You can get fancy with timeouts and peeking but typically people want aBlockingQueueinstance such asArrayBlockingQueue`。

    【讨论】:

      【解决方案4】:

      一个线程通知另一个线程不是一个好方法。最好有 1 个主线程让从属线程工作。从属线程始终在运行并等待直到它收到工作。我建议您绘制两列并准确确定每个线程需要等待的位置。

          public void run() 
          {
          //Do something big...
          synchronized(this)
          {
              done = true;
          }
          }
      

      Java 包含使这变得非常容易的库,请参阅ExecutorService 和以下帖子 Producer/Consumer threads using a Queue

      【讨论】:

        【解决方案5】:

        只需调用 notify()

        public void run() { 
            try { 
                while ( true ) { 
                    putMessage(); 
                    sleep( 1000 ); 
                } 
            }  
            catch( InterruptedException e ) { } 
        } 
        
        private synchronized void putMessage() throws InterruptedException { 
            while ( messages.size() == MAXQUEUE ) 
                wait(); 
        
            messages.addElement( new java.util.Date().toString() ); 
            notify(); 
        } 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多