一段代码分析 理解多线程交互

来源:互联网 发布:mac 终端 ip地址 编辑:程序博客网 时间:2024/06/05 06:17

                                                                                            

   

将notifyAll()移到synchronized代码块里面既可以解决异常

   
                       /**
* 计算线程
*/
public class Calculator extends Thread {
        int total;

        public void run() {
                synchronized (this) {
                        for (int i = 0; i < 101;i++) {
                                total+= i;
                        }
                }
                //通知所有在此对象上等待的线程
                notifyAll();
        }
}

 

/**
* 获取计算结果并输出
*
* @author leizhimin 2008-9-20 11:15:22
*/
class ReaderResult extends Thread {
        Calculator c;

        public ReaderResult(Calculator c) {
                this.c = c;
        }

        public void run() {
                synchronized (c) {
                        try {
                                System.out.println(Thread.currentThread()+ "等待计算结果。。。");
                                c.wait();
                        }catch(InterruptedException e) {
                                e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread()+ "计算结果为:" + c.total);
                }
        }

        public static void main(String[] args) {
                Calculatorcalculator = new Calculator();

                //启动三个线程,分别获取计算结果
                newReaderResult(calculator).start();
                newReaderResult(calculator).start();
                newReaderResult(calculator).start();
                //启动计算线程
                calculator.start();
        }
}

 

运行结果:

Thread[Thread-1,5,main]等待计算结果。。。
Thread[Thread-2,5,main]等待计算结果。。。
Thread[Thread-3,5,main]等待计算结果。。。
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current threadnot owner
  at java.lang.Object.notifyAll(Native Method)
  at threadtest.Calculator.run(Calculator.java:18)
Thread[Thread-1,5,main]计算结果为:5050
Thread[Thread-2,5,main]计算结果为:5050
Thread[Thread-3,5,main]计算结果为:5050

Process finished with exit code 0

      运行结果表明,程序中有异常,并且多次运行结果可能有多种输出结果。这就是说明,这个多线程的交互程序还存在问题。究竟是出了什么问题,需要深入的分析和思考,下面将做具体分析。

实际上,上面这个代码中,我们期望的是读取结果的线程在计算线程调用notifyAll()之前等待即可。但是,如果计算线程先执行,并在读取结果线程等待之前调用了notify()方法,那么又会发生什么呢?这种情况是可能发生的。因为无法保证线程的不同部分将按照什么顺序来执行。幸运的是当读取线程运行时,它只能马上进入等待状态----它没有做任何事情来检查等待的事件是否已经发生。  ----因此,如果计算线程已经调用了notifyAll()方法,那么它就不会再次调用notifyAll(),----并且等待的读取线程将永远保持等待。这当然是开发者所不愿意看到的问题。

     因此,当等待的事件发生时,需要能够检查notifyAll()通知事件是否已经发生。

     通常,解决上面问题的最佳方式是利用某种循环,该循环检查某个条件表达式,只有当正在等待的事情还没有发生的情况下,它才继续等待。

原创粉丝点击