Java线程使用同步锁交替执行打印奇数偶数的方法
对同一个对象进行多线程操作时,如何保证线程执行结果的一致性?我们需要对线程操作对象加同步锁。(这是一道面试题)
需求描述
1-20个数字
A线程打印奇数:1,3,5,7,9,11,13,15,17,19
B线程打印偶数:2,4,6,8,10,12,14,16,18,20
C线程在AB两个线程执行完了之后打印结果:“success”。
线程代码实现
Num.java
packagecom.boonya.thread.test; /** *@ClassName:Num *@Description:TODO(加锁计算对象) *@author:pengjunlin *@motto:学习需要毅力,那就秀毅力 *@date2019-01-1422:47 */ publicclassNum{ intvalue=1; }
AThread.java
packagecom.boonya.thread.test; /** *@ClassName:AThread *@Description:TODO(奇数线程) *@author:pengjunlin *@motto:学习需要毅力,那就秀毅力 *@date2019-01-1422:26 */ publicclassAThreadimplementsRunnable{ Numnum; publicAThread(Numnum){ this.num=num; } publicvoidrun(){ while(num.value<20){ synchronized(num){ if(num.value%2!=0){ System.out.println("AThread:"+num.value); num.value++; } } } } }
BThread.java
packagecom.boonya.thread.test; /** *@ClassName:BThread *@Description:TODO(偶数线程) *@author:pengjunlin *@motto:学习需要毅力,那就秀毅力 *@date2019-01-1422:26 */ publicclassBThreadimplementsRunnable{ Numnum; publicBThread(Numnum){ this.num=num; } publicvoidrun(){ while(num.value<=20){ synchronized(num){ if(num.value%2==0){ System.out.println("BThread:"+num.value); num.value++; } } } } }
CThread.java
packagecom.boonya.thread.test; /** *@ClassName:CThread *@Description:TODO(等待结果线程) *@author:pengjunlin *@motto:学习需要毅力,那就秀毅力 *@date2019-01-1422:26 */ publicclassCThreadimplementsRunnable{ Numnum; publicCThread(Numnum){ this.num=num; } publicvoidrun(){ while(num.value<20){ try{ Thread.sleep(1); }catch(InterruptedExceptione){ e.printStackTrace(); } } System.out.println("CThread:success!"); } }
MainTest.java
packagecom.boonya.thread.test; importjava.util.ArrayList; importjava.util.List; /** *@ClassName:MainTest *@Description:TODO(线程测试) *@author:pengjunlin *@motto:学习需要毅力,那就秀毅力 *@date2019-01-1421:54 */ publicclassMainTest{ publicstaticvoidmain(String[]args){ Numnum=newNum(); Threada=newThread(newAThread(num)); Threadb=newThread(newBThread(num)); Threadc=newThread(newCThread(num)); a.start(); b.start(); c.start(); } }
测试结果
"C:\ProgramFiles\Java\jdk1.8.0_121\bin\java""-javaagent:C:\Users\boonya\AppData\Roaming\JetBrains\IntelliJIDEA2017.2.5\lib\idea_rt.jar=51911:C:\Users\boonya\AppData\Roaming\JetBrains\IntelliJIDEA2017.2.5\bin"-Dfile.encoding=UTF-8-classpath"C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\charsets.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\deploy.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\access-bridge-64.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\cldrdata.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\dnsns.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\jaccess.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\jfxrt.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\localedata.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\nashorn.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\sunec.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\sunjce_provider.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\sunmscapi.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\sunpkcs11.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\ext\zipfs.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\javaws.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\jce.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\jfr.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\jfxswt.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\jsse.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\management-agent.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\plugin.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\resources.jar;C:\ProgramFiles\Java\jdk1.8.0_121\jre\lib\rt.jar;C:\Users\boonya\Desktop\JavaAlgorithm\target\test-classes;C:\Users\boonya\Desktop\JavaAlgorithm\target\classes"com.boonya.thread.test.MainTest AThread:1 BThread:2 AThread:3 BThread:4 AThread:5 BThread:6 AThread:7 BThread:8 AThread:9 BThread:10 AThread:11 BThread:12 AThread:13 BThread:14 AThread:15 BThread:16 AThread:17 BThread:18 AThread:19 BThread:20 CThread:success! Processfinishedwithexitcode0
注意:synchronized作为方法块使用时需要只能对对象加锁,不能是常用数据类型。
AB线程改进:使用线程等待和通知
AThread.java
packagecom.boonya.thread.test; /** *@ClassName:AThread *@Description:TODO(奇数线程) *@author:pengjunlin *@motto:学习需要毅力,那就秀毅力 *@date2019-01-1422:26 */ publicclassAThreadimplementsRunnable{ Numnum; publicAThread(Numnum){ this.num=num; } publicvoidrun(){ while(num.value<20){ synchronized(num){ if(num.value%2!=0){ System.out.println("AThread:"+num.value); num.value++; //num.notify(); num.notifyAll(); }else{ try{ num.wait(); }catch(InterruptedExceptione){ e.printStackTrace(); } } } } } }
BThread.java
packagecom.boonya.thread.test; /** *@ClassName:BThread *@Description:TODO(偶数线程) *@author:pengjunlin *@motto:学习需要毅力,那就秀毅力 *@date2019-01-1422:26 */ publicclassBThreadimplementsRunnable{ Numnum; publicBThread(Numnum){ this.num=num; } publicvoidrun(){ while(num.value<=20){ synchronized(num){ if(num.value%2==0){ System.out.println("BThread:"+num.value); num.value++; //num.notify(); num.notifyAll(); }else{ try{ num.wait(); }catch(InterruptedExceptione){ e.printStackTrace(); } } } } } }
注:线程等待和通知的操作是节省CPU运算的一种方式,避免CPU空转(线程方法一直不停地跑类似于死循环是很可怕的),如果是要让线程停下来需要调用线程的wait()。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。