线程之同步通信
所谓线程之同步通信,为了避免死锁,让线程在进入堵塞状态时尽量释放其锁定的资源,以为其他的线程提供运行的机会;
线程间的通信:
两个或两个以上的线程处理同一个资源,处理的动作是不一样的。
这样就需要将不同的动作代码放到不同的run方法中,run方法要封装到单独的类中。
同步中使用:
wait():让当前线程处于等待状态,释放cpu资源,同时释放锁。
notify():唤醒等待的线程,唤醒第一个
notifyAll():唤醒所以等待的线程。
//资源类
classRes{
Stringname;
Stringsex;
booleanb;
}
//生产者类
classInputimplementsRunnable{
privateResr;
publicInput(Resr){
this.r=r;
}
@Override
publicvoidrun(){
intx=0;
while(true){
synchronized(r){
//判断是否需要生产
if(r.b)
try{
r.wait();//释放cpu资源,同时释放锁
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
if(x==0){
r.name="张三";
r.sex="男";
}else{
r.name="lisi";
r.sex="nv";
}
r.b=true;
r.notify();
}
x=(x+1)%2;
}
}
}
//消费者类
classOutputimplementsRunnable{
privateResr;
publicOutput(Resr){
this.r=r;
}
@Override
publicvoidrun(){
while(true){
synchronized(r){
if(!r.b)
try{
r.wait();//释放cpu资源,同时释放锁
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
System.out.println(r.name+"...."+r.sex);
r.b=false;
r.notify();
}
}
}
}
publicclassThreadDemo4{
/**
*@paramargs
*/
publicstaticvoidmain(String[]args){
Resr=newRes();
Inputin=newInput(r);
Outputout=newOutput(r);
Threadt1=newThread(in);
Threadt2=newThread(out);
t1.start();
t2.start();
}
}
或者
packagecom.csdn;
publicclassThreadDemo5{
/**
*@paramargs
*/
publicstaticvoidmain(String[]args){
//TODOAuto-generatedmethodstub
Res1r=newRes1();
Input1in=newInput1(r);
Output1out=newOutput1(r);
Threadt1=newThread(in);
Threadt2=newThread(out);
t1.start();
t2.start();
}
}
classRes1{
privateStringname;
privateStringsex;
privatebooleanb;
publicsynchronizedvoidset(Stringname,Stringsex){
if(b){
try{
wait();
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
this.name=name;
this.sex=sex;
b=true;
notify();
}
publicsynchronizedvoidout(){
if(!b){
try{
wait();
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
System.out.println(name+"......"+sex);
b=false;
notify();
}
}
classInput1implementsRunnable{
privateRes1r;
publicInput1(Res1r){
this.r=r;
}
@Override
publicvoidrun(){
ints=0;
//TODOAuto-generatedmethodstub
while(true){
if(s==0){
r.set("小羊","男");
}else{
r.set("小猪","女");
}
s=(s+1)%2;
}
}
}
classOutput1implementsRunnable{
privateRes1r;
publicOutput1(Res1r){
this.r=r;
}
@Override
publicvoidrun(){
//TODOAuto-generatedmethodstub
while(true){
r.out();
}
}
}
这两个运行出来的结果是一样的,不过我比较喜欢第二种,可能是更具体,更简单,不像第一种那么复杂,把同步封装在资源里,然后底下直接调用即可;
wait():被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁,即解除了wait()方法当前对象的锁定状态,其他的线程就有机会访问该对象。
notify():唤醒调用wait()方法后被阻塞的线程。每次运行该方法只能唤醒一个线程。
notifyAll():唤醒所有调用wait()方法被阻塞的线程。