楼主今天在面经上看到这个题,挺有意思,小小的题目对多线程的考量还挺多。大部分同学都会使用 synchronized 来实现。

楼主今天带来另外两种优化实现,让你面试的时候,傲视群雄!

synchronized实现

class ThreadPrintDemo2 {public static void main(String[] args) {final ThreadPrintDemo2 demo2 = new ThreadPrintDemo2();Thread t1 = new Thread(demo2::print1);Thread t2 = new Thread(demo2::print2);t1.start();t2.start();}public synchronized void print2() {for (int i = 1; i <= 100; i += 2) {System.out.println(i);this.notify();try {this.wait();Thread.sleep(100);} catch (InterruptedException e) {}}}public synchronized void print1() {for (int i = 0; i <= 100; i += 2) {System.out.println(i);this.notify();try {this.wait();Thread.sleep(100);} catch (InterruptedException e) {}}}
}

通过 synchronized 同步两个方法,每次只能有一个线程进入,每打印一个数,就释放锁,另一个线程进入,拿到锁,打印,唤醒另一个线程,然后挂起自己。循环反复,实现了一个最基本的打印功能。面试常问的:Synchronized 有几种用法。

但,如果你这么写,面试官肯定是不满意的。楼主将介绍一种更好的实现。

CAS 实现

public class ThreadPrintDemo {static AtomicInteger cxsNum = new AtomicInteger(0);static volatile boolean flag = false;public static void main(String[] args) {Thread t1 = new Thread(() -> {for (; 100 > cxsNum.get(); ) {if (!flag && (cxsNum.get() == 0 || cxsNum.incrementAndGet() % 2 == 0)) {try {Thread.sleep(100);} catch (InterruptedException e) {}System.out.println(cxsNum.get());flag = true;}}});Thread t2 = new Thread(() -> {for (; 100 > cxsNum.get(); ) {if (flag && (cxsNum.incrementAndGet() % 2 != 0)) {try {Thread.sleep(100);} catch (InterruptedException e) {}System.out.println(cxsNum.get());flag = false;}}});t1.start();t2.start();}
}

我们通过使用 CAS,避免线程的上下文切换,然后呢,使用一个 volatile 的 boolean 变量,保证不会出现可见性问题,记住,这个 flag 一定要是 volatile 的,如果不是,可能你的程序运行起来没问题,但最终一定会出问题,而且面试官会立马鄙视你。面试常问的:深入理解CAS算法原理。

这样就消除了使用 synchronized 导致的上下文切换带来的损耗,性能更好。相信,如果你面试的时候,这么写,面试官肯定很满意。

但,我们还有性能更好的。

volatile实现

class ThreadPrintDemo3{static volatile int num = 0;static volatile boolean flag = false;public static void main(String[] args) {Thread t1 = new Thread(() -> {for (; 100 > num; ) {if (!flag && (num == 0 || ++num % 2 == 0)) {try {Thread.sleep(100);} catch (InterruptedException e) {}System.out.println(num);flag = true;}}});Thread t2 = new Thread(() -> {for (; 100 > num; ) {if (flag && (++num % 2 != 0)) {try {Thread.sleep(100);} catch (InterruptedException e) {}System.out.println(num);flag = false;}}});t1.start();t2.start();}
}

我们使用 volatile 变量代替 CAS 变量,减轻使用 CAS 的消耗,注意,这里 ++num 不是原子的,但不妨碍,因为有 flag 变量控制。而 num 必须是 volatile 的,如果不是,会导致可见性问题。

到这里,如果你面试的时候这么写,那么,offer 就不远啦!哈哈

【java】两个线程如何交替执行,一个输出偶数一个输出奇数?相关推荐

  1. 两个线程如何交替执行,一个输出偶数一个输出奇数?

    楼主今天在面经上看到这个题,挺有意思,小小的题目对多线程的考量还挺多.大部分同学都会使用 synchronized 来实现. 楼主今天带来另外两种优化实现,让你面试的时候,傲视群雄! synchron ...

  2. 多线程:Java两个线程,一个打印A-Z,另一个打印1-26,输出结果:A1 B2 C3 ...... Z26

    最近看到一个题,很有意思,就是在Java里实现两个线程,一个线程打印字母,也就是 ABCD - Z,另一个线程打印数字,也就是 1234 - 26.但是这两个线程需要交替打印:第一次字母线程先打印A, ...

  3. Java两个线程交替打印奇偶数(两种方法对比)

    简介 本文将承接文章<Java多线程wait()和notify()系列方法使用教程>,我们将通过"两个线程交替打印100内的奇偶数",来展示下wait()方法和noti ...

  4. 【完整代码】使用Semaphore实现线程的交替执行打印 A1B2C3D4E5

    import java.util.concurrent.Semaphore;/**使用Semaphore实现线程的交替执行打印 A1B2...Semaphore 基于AQS(内部维护了一个队列)可以用 ...

  5. 让两个线程有先后执行顺序

    让两个线程有先后执行顺序 public class Join1_One extends Thread {public void run(){System.out.println(Thread.curr ...

  6. 设计两个个线程模拟存取款操作,其中一个线程每次随机存1~1000元钱,另外一个线程取1-1000元钱,如果余额不足,则取款失败,提示余额不足。写出程序(考虑并发问题)。

    设计两个个线程模拟存取款操作,其中一个线程每次随机存1~1000元钱, 另外一个线程取1-1000元钱,如果余额不足,则取款失败,提示余额不足. 写出程序(考虑并发问题). import java.u ...

  7. 简单创建两个线程,交替输出内容

    简单创建两个线程,交替输出内容 package p1; public class Java_1 {//*********Found**********public static void main ( ...

  8. java两个线程交替执行

    比如有一个数,需要两个线程对其交替操作,代码如下 public class ThreadDemo {public static void main(String[] args) {Message me ...

  9. 进程有一个全局变量 i,还有有两个线程。i++ 在两个线程里边分别执行 100 次,能得到的最大值和最小值分别是多少?

    转自https://blog.csdn.net/biubiu741/article/details/77990592 多核CPU最小值为2,最大值200. 假设两个线程的执行步骤如下: 1. 线程A执 ...

最新文章

  1. 给Chrome“捉虫”16000个,Google开源bug自检工具
  2. 利用模拟退火提高Kmeans的聚类精度
  3. vue教程4:自定义组件的使用
  4. 当C++爬山壁纸——C++山寨版
  5. 安装SQL提示重启电脑失败,解决办法
  6. Linux下的用户和组
  7. Spring文件上传
  8. linux chmod 755 ,750,777
  9. 如何学习HyperMesh
  10. 【一起看花书1.1】——第五章 机器学习基础
  11. 手机远程访问HTML5,如何使用手机连接远程桌面?
  12. (亲测有效)windows10和11如何卸载Microsoft Edge浏览器
  13. go,go语言编辑器安装,git安装,即vscode三个插件的安装
  14. Linux中Sort命令详解
  15. android 支付宝未安装,调用支付宝接口Android客户端没有支付宝APP的情况下解决无法调用支付宝页面的问题...
  16. 3.0_Linux如何连接网络
  17. python从入门到实践16章答案
  18. 本项目基于paddlex实现目标检测
  19. 设备管理之I/O系统
  20. win10卸载WSL2记录

热门文章

  1. 苹果赢了!iOS14隐私功能并不违反法国反垄断法
  2. 富士康海外工厂遭黑客攻击 被勒索1804枚比特币
  3. 拼多多百亿补贴的iPhone 12来了 起售价5699元
  4. 京东健康上线“新冠病毒”核酸检测 在线预约服务
  5. 中兴通讯:将在全球范围内发布近10款5G手机
  6. 苹果悬赏100万美元找漏洞 辞职的理由找到了!
  7. 拼多多的车开向五环内!将继续撒钱,撒到你用为止...
  8. 蚂蚁金服回应海外和科创板上市传言:暂无上市时间表
  9. 情人节民宿预定量同比增200% 北京建国门最火
  10. 小米8青春版超级夜景安排上了 这个样张我是服气的!