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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。