易网时代-编程资源站
Welcome
微信登录
编程资源
图片资源库
蚂蚁家优选
PDF转换器
首页
/
操作系统
/
Linux
/
Java多线程之wait()和notify()
直接看测试代码吧,细节之处,详见注释
package
com.jadyer.thread.wait;
/**
* Java多线程之wait()和notify()的妙用
* @see =================================================================================================================
* @see 问题:同时启动两个线程和同时启动四个线程,控制台打印结果是不同的
* @see 同时启动两个线程时,控制台会很规律的输出1010101010101010
* @see 同时启动四个线程时,控制台起初会规律的输出10101010,一旦某一刻输出一个负数,那么后面的输出就会"一错再错"
* @see 分析:对线程而言,任何一种情况,都是合理的
* @see 这里假设其中的一种情况:tt22先执行,此时number=0,所以执行到了decrease()方法中的wait()方法,于是tt22被阻塞
* @see 接着tt44执行了,此时number=0,所以也执行到了decrease()方法中的wait()方法,于是tt44也被阻塞了
* @see 然后tt11执行了,此时number=0,www.linuxidc.com于是便执行到了increase()方法中的number++和notify()方法
* @see 重点在于tt11执行到notify()方法时,我们假设该方法唤醒了tt44线程,于是tt44开始执行decrease()方法中的number--
* @see 此时number=-1,然后执行到了decrease()方法中notify()方法,我们同样假设该notify()方法唤醒的是tt22线程
* @see 同样的道理,number又被减减了,于是number=-2,并被打印到控制台了,然后再假设tt22中的notify()方法唤醒的是tt11
* @see 如此的循环往复,就看到那种"一错再错"的效果了
* @see =================================================================================================================
* @see 修复:我们应当在wait()被唤醒的时候,再判断一次,然后再决定是否让该线程继续wait()下去
* @see 因为,当某个线程被唤醒时,它不知道外界在其睡眠的期间发生了神马,所以要再判断一次。所以把if()改为while()判断,即可
* @see =================================================================================================================
* @see 补充:如果只有两个线程的话,一个是对number增加的线程,一个是对number减少的线程,此时用if()判断是没有问题的
* @see 因为无论线程如何的唤醒,它所唤醒的都是另一个线程,不存在第三个线程插进来捣乱的情况
* @see =================================================================================================================
* @author 宏宇
* @create Feb 22, 2012 3:20:05 PM
*/
public
class
WaitNotifyTest {
public
static
void
main(String[] args) {
Count count =
new
Count();
Thread tt11 =
new
Thread(
new
IncreaseThread(count));
Thread tt22 =
new
Thread(
new
DecreaseThread(count));
Thread tt33 =
new
Thread(
new
IncreaseThread(count));
Thread tt44 =
new
Thread(
new
DecreaseThread(count));
tt11.start();
tt22.start();
tt33.start();
tt44.start();
}
}
class
IncreaseThread
implements
Runnable{
private
Count count;
public
IncreaseThread(Count count){
this
.count = count;
}
@Override
public
void
run() {
for
(
int
i=0; i<20; i++){
try
{
Thread.sleep((
long
)(Math.random()*1000));
}
catch
(InterruptedException e) {
e.printStackTrace();
}
count.increase();
}
}
}
class
DecreaseThread
implements
Runnable{
private
Count count;
public
DecreaseThread(Count count){
this
.count = count;
}
@Override
public
void
run() {
for
(
int
i=0; i<20; i++){
try
{
Thread.sleep((
long
)(Math.random()*1000));
}
catch
(InterruptedException e) {
e.printStackTrace();
}
count.decrease();
}
}
}
class
Count{
private
int
number;
public
synchronized
void
increase(){
if
(0 != number){
try
{
//在同步方法(或者同步语句块)中,被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁
//即解除了wait()方法所对应的当前对象的锁定状态,然后,其它的线程就有机会访问该对象了
wait();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
number++;
System.out.println(number);
//唤醒其它的由于调用了wait()方法而在等待同一个对象的线程
//该方法每次运行时,只能唤醒等待队列中的一个线程,至于是哪一个线程被唤醒,则由线程调度器来决定,程序员无法控制
notify();
}
public
synchronized
void
decrease(){
if
(0 == number){
try
{
wait();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
number--;
System.out.println(number);
notify();
}
}
收藏该网址
版权所有©石家庄振强科技有限公司2024
冀ICP备08103738号-5
网站地图