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

 更新时间:2019年01月30日 10:15:27   作者:boonya  
这篇文章主要介绍了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

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

AThread.java

package com.boonya.thread.test;
 
/**
* @ClassName: AThread
* @Description: TODO(奇数线程)
* @author: pengjunlin
* @motto: 学习需要毅力,那就秀毅力
* @date 2019-01-14 22:26
*/
public class AThread implements Runnable{
 
  Num num;
 
  public AThread(Num num){
    this.num=num;
  }
 
  public void run() {
    while (num.value<20){
      synchronized (num){
        if(num.value%2!=0){
          System.out.println("AThread:"+ num.value);
          num.value++;
        }
      }
    }
 
  }
}

BThread.java

package com.boonya.thread.test;
 
/**
 * @ClassName: BThread
 * @Description: TODO(偶数线程)
 * @author: pengjunlin
 * @motto: 学习需要毅力,那就秀毅力
 * @date 2019-01-14 22:26
 */
public class BThread implements Runnable {
 
    Num num;
 
    public BThread(Num num){
      this.num=num;
    }
 
    public void run() {
      while (num.value<=20){
        synchronized (num){
          if(num.value%2==0){
            System.out.println("BThread:"+ num.value);
            num.value++;
          }
        }
      }
    }
 }

CThread.java

package com.boonya.thread.test;
 
/**
 * @ClassName: CThread
 * @Description: TODO(等待结果线程)
 * @author: pengjunlin
 * @motto: 学习需要毅力,那就秀毅力
 * @date 2019-01-14 22:26
 */
public class CThread implements Runnable {
 
    Num num;
 
    public CThread(Num num){
      this.num=num;
    }
 
    public void run() {
      while (num.value<20){
        try {
          Thread.sleep(1);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      System.out.println("CThread:success!");
    }
  }

MainTest.java

package com.boonya.thread.test;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * @ClassName: MainTest
 * @Description: TODO(线程测试)
 * @author: pengjunlin
 * @motto: 学习需要毅力,那就秀毅力
 * @date 2019-01-14 21:54
 */
public class MainTest {
 
  public static void main(String[] args) {
    Num num=new Num();
    Thread a=new Thread(new AThread(num));
    Thread b=new Thread(new BThread(num));
    Thread c=new Thread(new CThread(num));
    a.start();
    b.start();
    c.start();
  }
}

测试结果

"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
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!
 
Process finished with exit code 0

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

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

AThread.java

package com.boonya.thread.test;
 
/**
* @ClassName: AThread
* @Description: TODO(奇数线程)
* @author: pengjunlin
* @motto: 学习需要毅力,那就秀毅力
* @date 2019-01-14 22:26
*/
public class AThread implements Runnable{
 
  Num num;
 
  public AThread(Num num){
    this.num=num;
  }
 
  public void run() {
    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 (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
 
  }
}

BThread.java

package com.boonya.thread.test;
 
/**
 * @ClassName: BThread
 * @Description: TODO(偶数线程)
 * @author: pengjunlin
 * @motto: 学习需要毅力,那就秀毅力
 * @date 2019-01-14 22:26
 */
public class BThread implements Runnable {
 
    Num num;
 
    public BThread(Num num){
      this.num=num;
    }
 
    public void run() {
      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 (InterruptedException e) {
              e.printStackTrace();
            }
          }
        }
      }
    }
 }

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 解决mybatis-generator生成Mapper文件没有Selective结尾的问题

    解决mybatis-generator生成Mapper文件没有Selective结尾的问题

    这篇文章主要介绍了解决mybatis-generator生成Mapper文件没有Selective结尾的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java实现WebSocket四个步骤

    Java实现WebSocket四个步骤

    这篇文章主要为大家介绍了Java实现WebSocket的方法实例,只需要简单四个步骤,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • 快速解决code唯一码(java)的简便方法

    快速解决code唯一码(java)的简便方法

    下面小编就为大家带来一篇快速解决code唯一码(java)的简便方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • JAVA SpringBoot jar程序 Systemctl生产环境部署方案

    JAVA SpringBoot jar程序 Systemctl生产环境部署方案

    这篇文章主要介绍了JAVA SpringBoot jar程序 Systemctl生产环境部署方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • Springboot使用slf4j记录日志的方法步骤

    Springboot使用slf4j记录日志的方法步骤

    本文主要介绍了Springboot使用slf4j记录日志的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • 聊聊Java Double相加出现的怪事

    聊聊Java Double相加出现的怪事

    这篇文章主要介绍了Java Double相加出现的怪事,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Springboot获取bean实例之SpringContextUtil详解

    Springboot获取bean实例之SpringContextUtil详解

    这篇文章主要介绍了Springboot获取bean实例之SpringContextUtil使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • 解决maven打包排除类不生效maven-compiler-plugin问题

    解决maven打包排除类不生效maven-compiler-plugin问题

    总结:在Spring Boot项目B中作为项目A的依赖时,排除启动类不生效的原因是被其他类引用或父POM引入,解决方法是跳过test编译或注释掉@SpringBootTest(classes={BApplication.class})
    2024-11-11
  • Spring的@RequestParam对象绑定方式

    Spring的@RequestParam对象绑定方式

    这篇文章主要介绍了Spring的@RequestParam对象绑定方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • java获取版本号及字节码编译版本方法示例

    java获取版本号及字节码编译版本方法示例

    这篇文章主要给大家介绍了关于java获得版本号及字节码编译版本的相关资料,文中通过示例代码介绍的非常详细,对大家学习或使用java具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-10-10

最新评论