2016-07-28 53 views
1

给定一个线程有多个状态:alive runnable运行等待并终止。notifyAll()方法假设将所有等待对象锁定的线程置回到“可运行”状态,在该状态下它可以被选为下一个运行对象。 以下示例实例化并启动3个读取器线程,它们将等待(wait()方法),直到释放'calc'对象的锁定。 calc对象线程被实例化并在此之后开始,在它之后加上一些数字,接着是notifyAll()。线程notifyAll()

我的问题是,为什么计算线程不会每次都通知所有的读线程?当我在电脑上运行它时,它会被击中并错过。

public class Reader extends Thread{ 
    Calculator c; 

    public Reader(Calculator calc){ 
     c=calc; 
    } 

    public void run(){ 
     synchronized(c){ 
      try{ 
       System.out.println("Waiting for calculation..."); 
       c.wait(); 
      }catch(InterruptedException e){} 
      System.out.println("Total is: "+c.total); 
     } 
    } 
    public static void main(String[] args){ 
     Calculator calc = new Calculator(); 
     new Reader(calc).start(); 
     new Reader(calc).start(); 
     new Reader(calc).start(); 
     new Thread(calc).start(); 
    } 
} 
class Calculator implements Runnable{ 
    int total; 

    public void run(){ 
     synchronized(this){ 
      for(int i =0; i<100; i++){ 
       total+=i; 
      } 
      notifyAll(); 
     } 
    } 
} 
+0

'notifyAll()'不_立即使线程RUNNABLE。它有效地将其状态从WAITING更改为BLOCKED。线程A中的'o.wait()'调用只有在线程A获得对象'o'上的锁定后才能返回,但当线程B调用'o.notifyAll()'时线程无法执行,因为线程B必须持有锁才能拨打该电话。 –

回答

1

当执行多个线程,线程的执行顺序是不保证

在您的案例中,Calculator线程完成循环,并且在Reader任何线程进入可运行状态之前调用notifyAll()。所以所有的Reader都会继续等待,永远不会打印total

为了避免出现这种情况,在这个特定的例子中,您可以使用Calculator中的另一个标志isCalculated,并在计算完成后设置该标志。 Reader线程也会检查此标志,并且只有在isCalculatedfalse时才会等待。

class Reader extends Thread { 
    Calculator c; 

    public Reader(Calculator calc) { 
    c = calc; 
    } 

    public void run() { 
    synchronized (c) { 
     try { 
     System.out.println("Waiting for calculation..."); 

     if (!c.isCalculated) { // wait only if calculation is not done 
      c.wait(); 
     } 
     } catch (InterruptedException e) { 
     } 
     System.out.println("Total is: " + c.total); 
    } 
    } 
} 

class Calculator implements Runnable { 
    int total; 
    boolean isCalculated; 

    public void run() { 
    synchronized (this) { 
     for (int i = 0; i < 100; i++) { 
     total += i; 
     } 

     isCalculated = true; // set flag to mark that computation is complete 
     notifyAll(); 
    } 
    } 
} 
+0

更好的是,我打算要求解决这个问题。谢谢。 – JensD

+0

不客气:) –

0

正如@Sudhir提到的,你可以调用wait, 检查本教程之前检查一些标志:http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

在你的情况notifyAll的()可以等待之前调用被称为..所以线程可能继续等待通知被称为

+0

并发性是我的书(塞拉利昂bates b java 7)的下一章。这是一本非常好的书,为我的OCP做准备。也许我通过问这个问题来跳枪,所有​​这些问题都很快就会公布。但是示例代码确实响了警钟。 – JensD

相关问题