当学到,包子铺,吃货案例时,我仍有很多疑惑,各个线程每行代码到时是怎样的执行,顺序怎么样,为什么用了锁,用了wait了就会变得有序起来
public static void main(String[] args) {
//创建锁对象,保证唯一
Object obj = new Object();
//创建一个顾客线程(消费者)
//创建一个老板线程(生产者)
new Thread(){
@Override
public void run() {
System.out.println("老板抢到了线程");
try {
//花了5秒做包子
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//保证等待和唤醒线程只能有一个执行,需要使用同步技术
synchronized (obj){
System.out.println("老板5秒钟后做好了包子,告知顾客,可以吃包子了");
//做好包子之后,调用notify方法,唤醒顾客吃包子
obj.notify();
}
}
}.start();
new Thread(){//匿名内部类
@Override
public void run() {//将run里面的代码放入while(true){}循环中达到循环线程通信
//保证等待和唤醒线程只能有一个执行,需要使用同步技术
System.out.println("顾客抢到了线程");
synchronized (obj){
System.out.println("告知老板要的包子的种类和数量");
//调用wait方法,放弃CPU的执行,进入到WAITING状态(无限等待)
try {
// Thread.sleep(5000);
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒之后执行的代码
System.out.println("包子已经到手了,开吃");
}
}
}.start();
}
写在前面的一句话,在这个案例中只要不处于sleep,wait,锁阻塞,代码都处于争夺cpu的过程
我在run放法下面各输出了两句话,当我执行整个代码的时候,我发现.这两句话的先后顺序是不确定的,随后两个线程再次进入抢夺cpu的执行
当老板先抢到cpu的时,执行sleep代码进入了沉睡阶段,注意一点,这个时候,老板线程是没有获得锁对象的,此时自然而然该轮到顾客线程获得cpu的执行,由于没有人获得锁对象,顾客立即获得锁对象,开始告知老板我要个包子,注意,执行这短话时,老板还处入睡眠,
我做了一下尝试,当我把这个沉睡时间代码注掉时再执行整个代码时,出现了两种情况
.一种是老板抢到了锁执行完了所有代码包括唤醒代码释放了锁,顾客输出了告知包子这段代码之后一直处于等待唤醒阶段,而整个程序一直处于正在执行,
至于另外一种我猜是正常的执行,顾客先获得锁对象告知了包子,接着处于等待释放锁,随后老板获得锁对象做完了包子并执行了唤醒代码当老板执行完synchronized代码块,释放锁对象.顾客被唤醒,执行了吃包子.果然程序正常终止了
若没有注掉这个沉睡时间,顾客是先于老板获得锁对象的,随后告知包子,进入wait,同时释放锁对象,当老板沉睡结束时,则会获得锁对象
执行输出包子做好了的代码,随后唤醒,注意这个时候notify还没有立刻释放锁,而是在整个synchronized代码块执行完释放锁对象,为此,我把synchronized代码块写个死循环,果然程序又处于一直执行