Java多线程通信:交替打印ABAB实例
使用wait()和notify()实现Java多线程通信:两个线程交替打印A和B,如ABABAB
publicclassTest{
publicstaticvoidmain(String[]args){
finalPrintABprint=newPrintAB();
newThread(newRunnable(){
publicvoidrun(){
for(inti=0;i<5;i++){
print.printA();
}
}
}).start();
newThread(newRunnable(){
publicvoidrun(){
for(inti=0;i<5;i++){
print.printB();}
}
}).start();
}
}
classPrintAB{
privatebooleanflag=true;
publicsynchronizedvoidprintA(){
while(!flag){
try{
this.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}}
System.out.print("A");
flag=false;
this.notify();
}
publicsynchronizedvoidprintB(){
while(flag){
try{
this.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
System.out.print("B");
flag=true;
this.notify();}
}
补充知识:Java多个线程顺序打印数字
要求
启动N个线程,这N个线程要不间断按顺序打印数字1-N.将问题简化为3个线程无限循环打印1到3
方法一:使用synchronized
三个线程无序竞争同步锁,如果遇上的是自己的数字,就打印.这种方式会浪费大量的循环
publicclassTestSequential1{
privatevolatileintpos=1;
privatevolatileintcount=0;
publicvoidone(inti){
synchronized(this){
if(pos==i){
System.out.println("T-"+i+""+count);
pos=i%3+1;
count=0;
}else{
count++;
}
}
}
publicstaticvoidmain(String[]args){
TestSequential1demo=newTestSequential1();
for(inti=1;i<=3;i++){
intj=i;
newThread(()->{
while(true){
demo.one(j);
}
}).start();
}
}
}
输出
T-10 T-25793 T-35285 T-12616 T-233 T-328 T-122 T-244 T-36 T-1881 T-2118358 T-3247380 T-130803 T-229627 T-352044 ...
方法二:使用synchronized配合wait()和notifyAll()
竞争同步锁时使用wait()和notifyAll(),可以避免浪费循环
publicclassTestSequential4{
privatevolatileintpos=1;
privatevolatileintcount=0;
privatefinalObjectobj=newObject();
publicvoidone(inti){
System.out.println(i+"try");
synchronized(obj){
System.out.println(i+"in");
try{
while(pos!=i){
count++;
System.out.println(i+"wait");
obj.wait();
}
System.out.println("T-"+i+""+count);
pos=i%3+1;
count=0;
obj.notifyAll();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
publicstaticvoidmain(String[]args){
TestSequential4demo=newTestSequential4();
for(inti=3;i>=1;i--){
intj=i;
newThread(()->{
while(true){
demo.one(j);
}
}).start();
}
}
}
输出
3try 3in 3wait 2try 2in 2wait 1try 1in T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 1try 1in 1wait T-21 2try 2in 2wait T-31 3try 3in 3wait 2wait T-12 ...
方法三:使用可重入锁
用Lock做,非公平锁,三个线程竞争,如果遇上的是自己的数字,就打印.这种方式也会浪费大量的循环
publicclassTestSequential2{
privatefinalLocklock=newReentrantLock();
privatevolatileintpos=1;
privatevolatileintcount=0;
publicvoidone(inti){
lock.lock();
if(pos==i){
System.out.println("T-"+i+""+count);
pos=i%3+1;
count=0;
}else{
count++;
}
lock.unlock();
}
publicstaticvoidmain(String[]args){
TestSequential2demo=newTestSequential2();
for(inti=1;i<=3;i++){
intj=i;
newThread(()->{
while(true){
demo.one(j);
}
}).start();
}
}
}
输出
T-10 T-20 T-3323 T-154 T-268964 T-397642 T-16504 T-2100603 T-36989 T-11313 T-20 T-3183741 T-1233 T-25081 T-3164367 ..
方法四:使用可重入锁,启用公平锁
和3一样,但是使用公平锁,这种情况下基本上可以做到顺序执行,偶尔会产生多一次循环
privatefinalLocklock=newReentrantLock(true);
输出
T-10 T-20 T-30 T-10 T-20 T-30 T-10 T-20 T-30 T-10 T-20 T-31 T-11 T-21 T-31 ...
方法五:使用Condition
每个线程如果看到不是自己的计数,就await(),如果是自己的计数,就完成打印动作,再signalAll()所有其他线程去继续运行,自己在下一个循环后,即使又继续执行,也会因为计数已经变了而await.
如果ReentrantLock构造参数使用true,可以基本消除~await这一步的输出.
publicclassReentrantLockCondition2{
privatestaticLocklock=newReentrantLock();
privatestaticConditioncondition=lock.newCondition();
privatevolatileintstate=1;
privatevoidhandle(intstate){
lock.lock();
try{
while(true){
while(this.state!=state){
System.out.println(state+"~await");
condition.await();
}
System.out.println(state);
this.state=state%3+1;
condition.signalAll();
System.out.println(state+"await");
condition.await();
}
}catch(InterruptedExceptione){
e.printStackTrace();
}finally{
lock.unlock();
}
}
publicstaticvoidmain(String[]args){
ReentrantLockCondition2rlc=newReentrantLockCondition2();
newThread(()->rlc.handle(1)).start();
newThread(()->rlc.handle(2)).start();
newThread(()->rlc.handle(3)).start();
}
}
方法六:使用多个Condition
给每个线程不同的condition.这个和4的区别是,可以用condition.signal()精确地通知对应的线程继续执行(在对应的condition上await的线程,可能是多个).这种情况下是可以多个线程都不unlock锁的情况下进行协作的.注意下面的while(true)循环是在lock.lock()方法内部的.
publicclassReentrantLockCondition{
privatestaticLocklock=newReentrantLock();
privatestaticCondition[]conditions={lock.newCondition(),lock.newCondition(),lock.newCondition()};
privatevolatileintstate=1;
privatevoidhandle(intstate){
lock.lock();
try{
while(true){
while(this.state!=state){
conditions[state-1].await();
}
System.out.println(state);
this.state=state%3+1;
conditions[this.state-1].signal();
conditions[state-1].await();
}
}catch(InterruptedExceptione){
e.printStackTrace();
}finally{
lock.unlock();
}
}
publicstaticvoidmain(String[]args){
ReentrantLockConditionrlc=newReentrantLockCondition();
newThread(()->rlc.handle(1)).start();
newThread(()->rlc.handle(2)).start();
newThread(()->rlc.handle(3)).start();
}
}
以上这篇Java多线程通信:交替打印ABAB实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。