Java总结篇系列:Java多线程(三)

来源:互联网 发布:word转换成excel软件 编辑:程序博客网 时间:2024/06/06 23:01
awAmount125      */126     public synchronized void draw(double drawAmount, int i) {127         if (!flag) {128             // 账户中还没人存钱进去,此时当前线程需要等待阻塞129             try {130                 System.out.println(Thread.currentThread().getName() + " 开始要执行wait操作" + " 执行了wait操作" + " -- i=" + i);131                 wait();132                 System.out.println(Thread.currentThread().getName() + " 执行了wait操作" + " 执行了wait操作" + " -- i=" + i);133             } catch (InterruptedException e) {134                 e.printStackTrace();135             }136         } else {137             // 开始取钱138             System.out.println(Thread.currentThread().getName() + " 取钱:" + drawAmount + " -- i=" + i);139             setBalance(getBalance() - drawAmount);140 141             flag = false;142 143             // 唤醒其他线程144             notifyAll();145 146             System.out.println(Thread.currentThread().getName() + "-- 取钱 -- 执行完毕" + " -- i=" + i); // 3147         }148     }149 150 }
复制代码

上面的例子演示了wait()/notify()/notifyAll()的用法。部分输出结果为:

复制代码
 1 取钱线程 开始要执行wait操作 执行了wait操作 -- i=0 2 存钱线程 存款:700.0 -- i=0 3 存钱线程-- 存钱 -- 执行完毕 -- i=0 4 存钱线程 开始要执行wait操作 -- i=1 5 取钱线程 执行了wait操作 执行了wait操作 -- i=0 6 取钱线程 取钱:700.0 -- i=1 7 取钱线程-- 取钱 -- 执行完毕 -- i=1 8 取钱线程 开始要执行wait操作 执行了wait操作 -- i=2 9 存钱线程 执行了wait操作 -- i=110 存钱线程 存款:700.0 -- i=211 存钱线程-- 存钱 -- 执行完毕 -- i=212 取钱线程 执行了wait操作 执行了wait操作 -- i=213 取钱线程 取钱:700.0 -- i=314 取钱线程-- 取钱 -- 执行完毕 -- i=315 取钱线程 开始要执行wait操作 执行了wait操作 -- i=416 存钱线程 存款:700.0 -- i=317 存钱线程-- 存钱 -- 执行完毕 -- i=318 存钱线程 开始要执行wait操作 -- i=419 取钱线程 执行了wait操作 执行了wait操作 -- i=420 取钱线程 取钱:700.0 -- i=521 取钱线程-- 取钱 -- 执行完毕 -- i=522 取钱线程 开始要执行wait操作 执行了wait操作 -- i=623 存钱线程 执行了wait操作 -- i=424 存钱线程 存款:700.0 -- i=525 存钱线程-- 存钱 -- 执行完毕 -- i=526 存钱线程 开始要执行wait操作 -- i=627 取钱线程 执行了wait操作 执行了wait操作 -- i=628 取钱线程 取钱:700.0 -- i=729 取钱线程-- 取钱 -- 执行完毕 -- i=730 取钱线程 开始要执行wait操作 执行了wait操作 -- i=831 存钱线程 执行了wait操作 -- i=632 存钱线程 存款:700.0 -- i=7
复制代码

由此,我们需要注意如下几点:

1.wait()方法执行后,当前线程立即进入到等待阻塞状态,其后面的代码不会执行;

2.notify()/notifyAll()方法执行后,将唤醒此同步锁对象上的(任意一个-notify()/所有-notifyAll())线程对象,但是,此时还并没有释放同步锁对象,也就是说,如果notify()/notifyAll()后面还有代码,还会继续进行,知道当前线程执行完毕才会释放同步锁对象;

3.notify()/notifyAll()执行后,如果右面有sleep()方法,则会使当前线程进入到阻塞状态,但是同步对象锁没有释放,依然自己保留,那么一定时候后还是会继续执行此线程,接下来同2;

4.wait()/notify()/nitifyAll()完成线程间的通信或协作都是基于不同对象锁的,因此,如果是不同的同步对象锁将失去意义,同时,同步对象锁最好是与共享资源对象保持一一对应关系;

5.当wait线程唤醒后并执行时,是接着上次执行到的wait()方法代码后面继续往下执行的。

当然,上面的例子相对来说比较简单,只是为了简单示例wait()/notify()/noitifyAll()方法的用法,但其本质上说,已经是一个简单的生产者-消费者模式了。

 

 

--------------------------------------------------------------------------------- 
笔者水平有限,若有错漏,欢迎指正,如果转载以及CV操作,请务必注明出处,谢谢!