示例代码取自传智播客毕向东老师25天Java基础教程,添加了一些观测打印代码,便于理解分析。对于进程分析理解纯粹个人理解,刚学Java没多久,难免有错,仅供参考,如果大神们发现错误,希望能帮忙指出,也帮我走出错误的理解。
先贴代码
class Res{
String name;
String sex;
boolean flag=false;
}
class Input implements Runnable{
private Res r;
public Input(Res r) {
this.r=r;
}
public void run() {
int k=0;
int a=0;//设定线程中有限次循环参数,便于观测运行数据
while (a<5) { //设定循环5次
synchronized(r) {//设定同一锁
if(r.flag)
try {
System.out.println("设置参数休眠");//用于观测本线程是否进入休眠
r.wait();
} catch (Exception e)
{}
if(k==0) {
r.name="Mike";
r.sex="man";
System.out.println("wozai mikezheli");//用于观测本是否进行此处成员变量赋值
}else {
r.name="丽丽";
r.sex="女女女女女女";
System.out.println("我在 丽丽这里");//用于观测本是否进行此处成员变量赋值
}
a++;
k=(k+1)%2;
r.flag=true;
r.notify();
}
}
}
}
class Output implements Runnable{
private Res r;
Output(Res r){
this.r=r;
}
public void run() {
int b=0;
while (b<5) {
synchronized(r) {
if(!r.flag)
try {
System.out.println("打印参数休眠*****");//用于观测本线程是否进入休眠
r.wait();
} catch (Exception e)
{}
System.out.println(Thread.currentThread().getName()+r.name+"------"+r.sex);
b++;
r.flag=false;
r.notify();
}
}
}
}
public class InOutput {
public static void main(String[] args) {
Res r=new Res();
Input in=new Input(r);
Output out=new Output(r);
Thread t1=new Thread(in);
Thread t2=new Thread(out);
t1.start();
t2.start();
}
}
运行结果:1、
wozai mikezheli
打印输出线程b Mike------man
打印参数休眠*****
我在 丽丽这里
打印输出线程b 丽丽------女女女女女女
打印参数休眠*****
wozai mikezheli
打印输出线程b Mike------man
打印参数休眠*****
我在 丽丽这里
打印输出线程b 丽丽------女女女女女女
打印参数休眠*****
wozai mikezheli
打印输出线程b Mike------man
这是出现最多的一种结果。首先赋值线程a启动,进入while循环,经同步锁进入同步代码块中,if(r.flag)判定,线程a未进入等待,直接进行if(k==0)判定,分别赋值Mike和man,此时和输出我们设定的观测语句“wozai mikezheli”,运行完接下来的语句且唤醒线程b,结束同步代码块。注意:此时线程a与b都是就绪状态,都可执行!!由结果可知,线程a再次抢夺到运行资质(NB啊),经同步锁进入同步代码块中,if(r.flag)判定,线程a进入等待(白抢了),同时放弃已占有的同步锁资源。线程b经同步锁进入同步代码块,经if(!r.flag)判断,线程b未进行等待。执行代码输出语句“打印输出线程b Mike------man”,运行完接下来的语句且唤醒线程a,结束同步代码块。此时a与b又都进入到就绪状态,抢夺执行权。由结果知b抢到了,但由于判断条件的参数改变,只能去等待,a执行赋值后唤醒b,结束同步代码块。再次竞争。。。。不管哪次竞争结果如何,如果刚执行完的线程抢到,由于参数设置的改变,都只能进入等待,对外表现为两线程交替执行。如果俩线程都处于就绪状态,竞争应该一直存在,未必只发生在俩线程都在同步代码块外面的时候,只不过,某一线程即使争到了也进不去同步锁或只能进入等待。以上分析大概率是错的,对于编程知道的太少了,只是现阶段的个人理解。
还有一种比较特别的结果(运行很多次会出现):
打印参数线程b休眠*****
wozai mikezheli
打印输出线程b Mike------man
打印参数线程b休眠*****
我在 丽丽这里
设置参数线程a休眠
打印输出线程b 丽丽------女女女女女女
打印参数线程b休眠*****
wozai mikezheli
设置参数线程a休眠
打印输出线程b Mike------man
打印参数线程b休眠*****
我在 丽丽这里
设置参数线程a休眠
打印输出线程b 丽丽------女女女女女女
打印参数线程b休眠*****
wozai mikezheli
打印输出线程b Mike------man
虽然线程a在主线程中先启动,线程b后启动,但是在第一次的竞争中还是输了,唉。。
学习Java三十多天,对于编程知识所知太少,分享只为交流个人理解,仅供参考,难免有错。希望有大神如果发现我理解中的错误,一定指出来!
对了,上面应该是等待,不是休眠!!