2012-12-14 78 views
0

我有2个班。该类的一个方法调用另一个类的方法,但它必须等到该方法结束才能继续执行其余的代码。如何在这种情况下实现线程等待通知?

这是我试图做的粗略代码。我知道这是行不通的。

public class Example 
{ 
    Thread thread; 

    public Example(Thread thread) 
    { 
     this.thread = thread; 
    } 

    public void doSomethingElse() 
    { 
     System.out.println("Do something else"); 
     thread.notify(); 
    } 
} 

public class Example2 
{ 
    Thread thread; 
    Example example; 

    public Example2() 
    { 
     example = new Example(thread); 
     thread = new Thread() 
     { 
      public void run() 
      { 
       example.doSomethingElse(); 
       try { 
        this.wait(); 
       } catch (InterruptedException ex) {      
       } 
       System.out.println("Do something"); 
      } 
     }; 
    } 

    public void doSomething() 
    { 
     thread.run(); 
    } 
} 

现在你知道怎么解决这个问题了吗?

回答

0

不知道如果你限制使用这种特殊的方法(等待/通知),但更好的方法是采取的Java Concurrency API

public class ExampleCountDownLatch 
{ 
    public void doSomething() throws InterruptedException 
    { 
     final CountDownLatch latch = new CountDownLatch(1); 

     Thread thread = new Thread() 
     { 
      public void run() 
      { 
       System.out.println("do something"); 
       latch.countDown(); 
      } 
     }; 

     System.out.println("waiting for execution of method in your example class"); 
     thread.start(); 
     // wait for reasonable time otherwise kill off the process cause it took 
     // too long. 
     latch.await(3000, TimeUnit.MILLISECONDS); 

     // now I can do something from your example 2 
     System.out.println("now i can execute from example 2 do something else"); 
    } 
} 
优势

无论如何,如果你有一个选项,只是另一种方法。

UPDATE:

这里有一个关于这个非常topic博客。

+0

谢谢youuu !!!! – William

0

几点:

  • 你应该调用wait之前获得锁或通知方法。锁必须位于同一个对象上。在代码中,您正在呼叫等待example2 对象,但调用通知不同的对象。
  • thread.run()表示调用线程对象的运行方法,其不是 创建与example.doSomething()相同的新线程。当你通过调用start方法创建线程启动该线程时。

这是我实现

class Example implements Runnable 
    { 
     public void run() 
     { 
      doSomething(); 
     } 
     public void doSomething(){ 
      synchronized(this){ 
       System.out.println("Do something else"); 
       try{ 
        Thread.sleep(1000); 
        this.notify();  
       }catch (InterruptedException ignore) {}    
      }  
     } 
    } 

    class Example2 implements Runnable 
    { 
     Thread thread; 
     Example example; 

     public Example2(Example example){ 
      this.example = example; 
     } 


     public void run(){ 
      doSomething();  
     } 

     public void doSomething(){ 
      synchronized(example){ 
       System.out.println("waiting for example 1 to complete"); 
       try{ 
        example.wait();  
       }catch (InterruptedException ignore) {} 

      } 
      System.out.println("Do something"); 
     } 
    } 

    public class Entry{ 
     public static void main(String[] args){ 

      Example example = new Example(); 

      Example2 obj = new Example2(example); 
      Thread t = new Thread(obj); 
      t.start(); 

      Thread t2 = new Thread(example); 
      t2.start(); 
     } 
    } 

在代码中的Thread.sleep(1000);声明是不需要的。

+1

还有几点:a)如果'wait'之前调用'notify',则建议的解决方案会挂起。由于该方法在并行线程上调用,因此可能会发生这种情况。为了避免这种情况,需要额外的变量,表示作业已完成。通常这样的变量包含结果。在调用“wait”之前应该检查它。 b)应该在循环中调用'wait',以忽略虚假通知。 –

0

下面是使用join方法多了一个实现

class Example implements Runnable 
    { 
     public void run() 
     { 
      doSomething(); 
     } 
     public void doSomething(){ 
      System.out.println("Do something else"); 

      try{ 
       Thread.sleep(1000);  
      }catch (InterruptedException ignore) {}     
     } 
    } 

    class Example2 implements Runnable 
    { 
     Thread thread; 
     Example example; 

     public Example2(Example example){ 
      this.example = example; 
     } 


     public void run(){ 
      System.out.println("waiting for example 1 to complete"); 
      Thread t = new Thread(example); 
      try{ 
       t.start(); 
       t.join(); 
      }catch(InterruptedException ie){ 

      } 

      doSomething();  
     } 

     public void doSomething(){ 
      System.out.println("Do something"); 
     } 
    } 

    public class Entry{ 
     public static void main(String[] args){ 

      Example example = new Example(); 

      Example2 obj = new Example2(example); 
      Thread t = new Thread(obj); 
      t.start(); 
     } 
    }