关键词搜索

源码搜索 ×
×

Java线程使用同步锁交替执行打印奇数偶数

发布2019-01-14浏览3761次

详情内容

对同一个对象进行多线程操作时,如何保证线程执行结果的一致性?我们需要对线程操作对象加同步锁。(这是一道面试题)

需求描述

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

  1. package com.boonya.thread.test;
  2. /**
  3. * @ClassName: Num
  4. * @Description: TODO(加锁计算对象)
  5. * @author: pengjunlin
  6. * @motto: 学习需要毅力,那就秀毅力
  7. * @date 2019-01-14 22:47
  8. */
  9. public class Num {
  10. int value=1;
  11. }

AThread.java

  1. package com.boonya.thread.test;
  2. /**
  3. * @ClassName: AThread
  4. * @Description: TODO(奇数线程)
  5. * @author: pengjunlin
  6. * @motto: 学习需要毅力,那就秀毅力
  7. * @date 2019-01-14 22:26
  8. */
  9. public class AThread implements Runnable{
  10. Num num;
  11. public AThread(Num num){
  12. this.num=num;
  13. }
  14. public void run() {
  15. while (num.value<20){
  16. synchronized (num){
  17. if(num.value%2!=0){
  18. System.out.println("AThread:"+ num.value);
  19. num.value++;
  20. }
  21. }
  22. }
  23. }
  24. }

BThread.java

  1. package com.boonya.thread.test;
  2. /**
  3. * @ClassName: BThread
  4. * @Description: TODO(偶数线程)
  5. * @author: pengjunlin
  6. * @motto: 学习需要毅力,那就秀毅力
  7. * @date 2019-01-14 22:26
  8. */
  9. public class BThread implements Runnable {
  10. Num num;
  11. public BThread(Num num){
  12. this.num=num;
  13. }
  14. public void run() {
  15. while (num.value<=20){
  16. synchronized (num){
  17. if(num.value%2==0){
  18. System.out.println("BThread:"+ num.value);
  19. num.value++;
  20. }
  21. }
  22. }
  23. }
  24. }

CThread.java

  1. package com.boonya.thread.test;
  2. /**
  3. * @ClassName: CThread
  4. * @Description: TODO(等待结果线程)
  5. * @author: pengjunlin
  6. * @motto: 学习需要毅力,那就秀毅力
  7. * @date 2019-01-14 22:26
  8. */
  9. public class CThread implements Runnable {
  10. Num num;
  11. public CThread(Num num){
  12. this.num=num;
  13. }
  14. public void run() {
  15. while (num.value<20){
  16. try {
  17. Thread.sleep(1);
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. System.out.println("CThread:success!");
  23. }
  24. }

MainTest.java

  1. package com.boonya.thread.test;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * @ClassName: MainTest
  6. * @Description: TODO(线程测试)
  7. * @author: pengjunlin
  8. * @motto: 学习需要毅力,那就秀毅力
  9. * @date 2019-01-14 21:54
  10. */
  11. public class MainTest {
  12. public static void main(String[] args) {
  13. Num num=new Num();
  14. Thread a=new Thread(new AThread(num));
  15. Thread b=new Thread(new BThread(num));
  16. Thread c=new Thread(new CThread(num));
  17. a.start();
  18. b.start();
  19. c.start();
  20. }
  21. }

测试结果

  1. "C:\Program Files\Java\jdk1.8.0_121\bin\java" "-javaagent:C:\Users\boonya\AppData\Roaming\JetBrains\IntelliJ IDEA 2017.2.5\lib\idea_rt.jar=51911:C:\Users\boonya\AppData\Roaming\JetBrains\IntelliJ IDEA 2017.2.5\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_121\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_121\jre\lib\resources.jar;C:\Program Files\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
  2. AThread:1
  3. BThread:2
  4. AThread:3
  5. BThread:4
  6. AThread:5
  7. BThread:6
  8. AThread:7
  9. BThread:8
  10. AThread:9
  11. BThread:10
  12. AThread:11
  13. BThread:12
  14. AThread:13
  15. BThread:14
  16. AThread:15
  17. BThread:16
  18. AThread:17
  19. BThread:18
  20. AThread:19
  21. BThread:20
  22. CThread:success!
  23. Process finished with exit code 0

注意:synchronized 作为方法块使用时需要只能对对象加锁,不能是常用数据类型。

AB线程改进:使用线程等待和通知

AThread.java

  1. package com.boonya.thread.test;
  2. /**
  3. * @ClassName: AThread
  4. * @Description: TODO(奇数线程)
  5. * @author: pengjunlin
  6. * @motto: 学习需要毅力,那就秀毅力
  7. * @date 2019-01-14 22:26
  8. */
  9. public class AThread implements Runnable{
  10. Num num;
  11. public AThread(Num num){
  12. this.num=num;
  13. }
  14. public void run() {
  15. while (num.value<20){
  16. synchronized (num){
  17. if(num.value%2!=0){
  18. System.out.println("AThread:"+ num.value);
  19. num.value++;
  20. //num.notify();
  21. num.notifyAll();
  22. }else{
  23. try {
  24. num.wait();
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. }
  31. }
  32. }

BThread.java

  1. package com.boonya.thread.test;
  2. /**
  3. * @ClassName: BThread
  4. * @Description: TODO(偶数线程)
  5. * @author: pengjunlin
  6. * @motto: 学习需要毅力,那就秀毅力
  7. * @date 2019-01-14 22:26
  8. */
  9. public class BThread implements Runnable {
  10. Num num;
  11. public BThread(Num num){
  12. this.num=num;
  13. }
  14. public void run() {
  15. while (num.value<=20){
  16. synchronized (num){
  17. if(num.value%2==0){
  18. System.out.println("BThread:"+ num.value);
  19. num.value++;
  20. //num.notify();
  21. num.notifyAll();
  22. }else{
  23. try {
  24. num.wait();
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. }
  31. }
  32. }

注:线程等待和通知的操作是节省CPU运算的一种方式,避免CPU空转(线程方法一直不停地跑类似于死循环是很可怕的),如果是要让线程停下来需要调用线程的wait()。

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载