两个线程按顺序交替输出1-100

继承Thread类,实现Runnable接口均可

方法一:使用synchronized关键字

public class PrintNumber extends Thread {private static int cnt = 0;private int id;  // 线程编号public PrintNumber(int id) {this.id = id;}@Overridepublic void run() {while (cnt <= 100) {if (cnt%2 == id) {synchronized (PrintNumber.class) {cnt++;System.out.println("thread_" + id + " num:" + cnt);}}}}public static void main(String[] args) {Thread thread0 = new PrintNumber(0);Thread thread1 = new PrintNumber(1);thread0.start();thread1.start();}
}

方法二:使用synchronized关键字,wait和notify

public class PrintNumber extends Thread {private static int cnt = 0;private int id;  // 线程编号public PrintNumber(int id) {this.id = id;}@Overridepublic void run() {while (cnt <= 100) {synchronized (PrintNumber.class) {cnt++;System.out.println("thread_" + id + " num:" + cnt);PrintNumber.class.notify();try {PrintNumber.class.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {Thread thread0 = new PrintNumber(0);Thread thread1 = new PrintNumber(1);thread0.start();thread1.start();}
}
public class Test {public static void main(String[] args){Number number = new Number();Thread t1 = new Thread(number);Thread t2 = new Thread(number);t1.setName("线程1");t2.setName("线程2");t1.start();t2.start();}}class Number implements Runnable{private int number = 1;@Overridepublic void run(){while(number <= 100){synchronized(this){System.out.println(number);number++;notify();try{if(number <= 100){wait();}}catch (InterruptedException e) {e.printStackTrace();}}}}
}

方法三:使用ReentrantLock

把synchronized换成lock,然后把wait和notify换成Condition的signal和await

public class PrintNumber extends Thread {private static Lock lock = new ReentrantLock();private static Condition condition = lock.newCondition();private int id;private static int cnt = 0;public PrintNumber(int id) {this.id = id;}private static void print(int id) {}@Overridepublic void run() {while (cnt <= 100) {lock.lock();System.out.println("thread_" + id + " num:" + cnt);cnt++;condition.signal();try {condition.await();} catch (InterruptedException e) {e.printStackTrace();}lock.unlock();}}public static void main(String[] args) {Thread thread0 = new PrintNumber(0);Thread thread1 = new PrintNumber(1);thread0.start();thread1.start();}
}

方法四:不使用锁,利用volatile实现

//两个线程,一个打印奇数,一个打印偶数
public class OneToHundred{static volatile int flag = 0;public static void main(String[] args){new Thread(new Task1(),"A").start();new Thread(new Task2(),"B").start();}
}class Task1 implements Runnable{@Overridepublic void run(){int i = -2;while(i<=99){if(OneToHundred.flag == 0){i+=2;System.out.println("a:" + i);OneToHundred.flag = 1;}}}
}class Task2 implements Runnable{@Overridepublic void run(){int i = -1;while(i<=98){if(OneToHundred.flag == 1){i+=2;System.out.println("b:" + i);OneToHundred.flag = 0;}}}
}

方法五:使用AtomicInteger

public class PrintNumber extends Thread {private static AtomicInteger cnt = new AtomicInteger();private int id;public PrintNumber(int id) {this.id = id;}@Overridepublic void run() {while (cnt.get() <= 100) {if (cnt.get()%2 == id) {System.out.println("thread_" + id + " num:" + cnt.get());cnt.incrementAndGet();}}}public static void main(String[] args) {Thread thread0 = new PrintNumber(0);Thread thread1 = new PrintNumber(1);thread0.start();thread1.start();}
}

扩展问题

  1. 如果是三个线程交替输出呢?
    解析:三个线程的解法可以使用while (cnt%3 == id)的方式实现忙等,但简单的唤醒+等待的方式必然不适用了, 没有判断的synchronized必然实现不了,java Object的notify和wait方法只能唤醒全部线程,然后另外两个线程输出前都需要额外判断下是否轮到自己输出了。这时候lock中condition的优势就体现出来了,它可以通过设置不同的condition来实现不同线程的精确唤醒。
public class Test {volatile int i = 1;public static void main(String[] args) throws Exception {Test obj = new Test();Runnable runnable = new Runnable() {@Overridepublic void run() {while (obj.i <= 100) {// 上锁当前对象synchronized (this) {// 唤醒另一个线程notifyAll();if (obj.i == 101) {return;}int i = new Integer(Thread.currentThread().getName());if (obj.i % 3 == i) {System.out.println("Thread " + Thread.currentThread().getName() + " " + obj.i++);}if(obj.i % 3==1){System.out.println("==========");}try {if (obj.i == 101) {notifyAll();return;} else {// 释放掉锁wait();}} catch (Exception e) {e.printStackTrace();}}}}};// 启动多个线程(想创建几个就创建几个)Thread t1 = new Thread(runnable);Thread t2 = new Thread(runnable);Thread t3 = new Thread(runnable);t1.setName("1");t2.setName("2");t3.setName("0");t1.start();t2.start();t3.start();}
}
    public static void main(String[] args){Thread thread0 = new PrintNumber(0);Thread thread1 = new PrintNumber(1);Thread thread2 = new PrintNumber(2);thread0.start();thread1.start();thread2.start();}class PrintNumber extends Thread{private static int cnt = 0;private int id;  // 线程编号public PrintNumber(int id) {this.id = id;}@Overridepublic void run() {while (cnt < 100) {if (cnt % 3 == id) {synchronized (PrintNumber.class) {cnt++;System.out.println("thread_" + id + " num:" + cnt);}}}}
}

并发编程-两个线程交替操作相关推荐

  1. 使用Java线程并发库实现两个线程交替打印的线程题

    背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题.晚上闲着没事就决定把它实现出来. 题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交 ...

  2. java并发编程实践(2)线程安全性

    [0]README 0.0)本文部分文字描述转自:"java并发编程实战", 旨在学习"java并发编程实践(2)线程安全性" 的相关知识: 0.1)几个术语( ...

  3. 线程打印_经典面试题——两个线程交替打印奇数和偶数

    前提 今天下班时候和同事聊天偶然听到面试题"两个线程交替打印奇数和偶数"的实现,这里做一个复盘. 复盘 场景一:线程A打印奇数,线程B打印偶数,线程A和线程B交替打印,使用对象监视 ...

  4. 利用两个线程验证 ++ 操作是非原子性的

    以下示例代码将演示 ++ 操作是非线程安全的,具体看注释的解释,仔细阅读和多次对比执行结果时,也许还能体验到线程被调度执行的随机性,或许对某些读者会有帮助. 还同时对比演示了synchronized关 ...

  5. java go多线程:两个线程交替打印 0~100 的奇偶数

    最近在实现raft算法,用到了很多go的高并发的知识,看到一道题写两个线程交替打印 1~100 的奇偶数,突然来了兴趣. 题目要求我们要启动两个线程,一个打印奇数,一个打印偶数.中途不能跳出协程. 代 ...

  6. Java常见的面试算法题:实现两个线程交替打印1到100的数

    Java常见的面试算法题:实现两个线程交替打印1到100的数 思路: 这是涉及到多个线程打印的问题,一定会用到锁的(synchronized),故这就是一个多线程打印的典型案例. 代码实现: pack ...

  7. 学习笔记(33):Python网络编程并发编程-进程池线程池

    立即学习:https://edu.csdn.net/course/play/24458/296451?utm_source=blogtoedu 进程池与线程池: 一般应用在网站上,进程池或线程池最大的 ...

  8. 线程打印_面试题:用程序实现两个线程交替打印 0~100 的奇偶数

    作者:dadiyang来源:https://blog.csdn.net/dadiyang/article/details/88315124 面试场景 面试官:Java多线程了解吗?你给我写一下,起两个 ...

  9. 如何让两个线程交替打印整数1-100?你的答案呢?

    前端时间下班临走前看到同事做尝试的一个题目:如何让两个线程交替打印整数1-100? 好几年没有写代码玩了,想了想,花了十多分钟写了个答案: #include<stdio.h> #inclu ...

最新文章

  1. php提供的用户密码加密函数
  2. Zookeeper服务器集群的搭建与操作
  3. 测试一下能够图文混排
  4. 1.7 Appium依赖添加
  5. 面试重点:设计模式(二)——创建模式
  6. CRMEB页面说明这个是v3.0H5端的
  7. tensorflow对应的cudnn、cuda版本
  8. python源码编译安装 gb18030_源代码编译安装Python3.5.2
  9. leetcode455. 分发饼干
  10. smart700iev3 程序下载设置_分享一款Aira2下载工具
  11. html css怎么连在一起,CSS秘密花园:连体字母_html/css_WEB-ITnose
  12. linux安装之后缺少命令,CentOS7安装成功后缺少命令的解决办法
  13. dot language 学习笔记
  14. matplotlib绘制圆饼图
  15. 关于邮箱的POP协议、imap协议、imap协议简单讲解
  16. mysql-repeatable read可以避免幻读
  17. 伪原创内容来源的八个渠道
  18. [LetCode-1438] 绝对差不超过限制的最长连续子数组
  19. iOS开发人员必看的精品资料(100个)——下载目录
  20. Android CardView 不显示阴影

热门文章

  1. 营养素揭秘:合成营养素与天然营养素真的有区别吗?
  2. 探索云原生技术之容器编排引擎-Kubernetes/K8S详解(6)
  3. el-date-picker中自定义快捷选项picker-options,动态设置禁用日期
  4. 国家开放大学-乡村社会学-形考作业2
  5. navicat无法连接远程mysql数据库_[数据库]Navicat Premium 解决无法连接远程mysql数据库问题...
  6. 口水战,实在是费心费力,浪费时间,以后坚持8020法则,决不手软!
  7. 虚拟恋人会是孤独的自我救赎吗?
  8. excel导出java.lang.ArrayIndexOutOfBoundsException: 0 POI导出excel报错数组下标越界0
  9. Launch screens may not set custom classnames
  10. GeoGebra介绍