主要是利用线程的wait()和notify()来实现

public class MyThread implements Runnable {
private String name;
private Object prev;
private Object mine; private MyThread(String name,Object prev,Object mine){
this.name = name;
this.prev = prev;
this.mine = mine;
} @Override
public void run() {
int count = 10;
while(count > 0){
synchronized (prev) {
synchronized (mine) {
System.out.println(name);
count--;
mine.notify();
} try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
} }
} } public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThread pa = new MyThread("A", c, a);
MyThread pb = new MyThread("B", a, b);
MyThread pc = new MyThread("C", b, c);
new Thread(pa).start();
new Thread(pb).start();
new Thread(pc).start(); } }

整理下程序的思路:因3个线程要按照顺序打印ABC,那么应该是ThreadA->ThreadB->ThreadC->ThreadA如此循环,当运行ThreadA时,prev对象是c,mine对象是a,打印A,然后唤醒线程a,最后让当前线程c等待,则ThreadA进入等待(注意此时调用的prev.wait()虽然让线程进入了等待,但同时也释放了对象的锁,其他线程可以访问此同步方法)。ThreadB的prev对象是a,mine对象是b,打印B;而ThreadC的prev对象是b,mine对象是c;其实这种方式不一定能完全保证是ABC的顺序输出,因为看程序,B线程在等待a对象的锁,获取a的锁才能继续向下进行,而C线程在如果抢先运行的话,b的锁是不需要等待的,则直接等待a的锁,在ThreadA运行完毕释放锁后,若C线程率先获取a的锁的话,那么打印顺序就会遭到改变。所以若要让线程A、B、C按照顺序执行的话,一定要让3个线程按照顺序执行。更改程序为:

 public class MyThread implements Runnable {
private String name;
private Object prev;
private Object mine; private MyThread(String name,Object prev,Object mine){
this.name = name;
this.prev = prev;
this.mine = mine;
} @Override
public void run() {
int count = 10;
while(count > 0){
synchronized (prev) {
synchronized (mine) {
System.out.println(name);
count--;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
mine.notify();
} try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
} }
} } public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThread pa = new MyThread("A", c, a);
MyThread pb = new MyThread("B", a, b);
MyThread pc = new MyThread("C", b, c);
try {
new Thread(pa).start();
Thread.sleep(10);
new Thread(pb).start();
Thread.sleep(10);
new Thread(pc).start();
} catch (InterruptedException e) {
e.printStackTrace();
} } }

这样就能真正的实现,第一遍运行顺序为ThreadA打印A,然后ThreadA等待->ThreadB打印B,然后B等待->ThreadC打印C,然后C等待并唤醒A;以此循环打印了。

文章思路不是很清晰,主要还是学习别人写的东西,转化成自己能够理解的语言。努力学习中!

多线程循环打印ABC的更多相关文章

  1. Java多线程循环打印ABC的5种实现方法

    https://blog.csdn.net/weixin_39723337/article/details/80352783 题目:3个线程循环打印ABC,其中A打印3次,B打印2次,C打印1次,循环 ...

  2. python 多线程实现循环打印 abc

    python 多线程实现循环打印 abc 好久没写过python了, 想自己实践一下把 非阻塞版 import threading import time def print_a(): global ...

  3. 多线程循环打印数组 -- Java笔记

    问题描述: 现有多个长度相同的数组,现要求使用多线程将数组内的数交替打印. 如: int[] ai = {1,2,3,4,5,6,7}; String[] ac = {"A",&q ...

  4. JAVA 多线程轮流打印ABC

    采用Thread+Semaphore实现,思路很简单 import java.io.IOException; import java.util.concurrent.Semaphore; public ...

  5. python多线程交替打印abc以及线程池进程池的相关概念

    import threading import sys import time def showa(): while True: lockc.acquire() #获取对方的锁,释放自己的锁 prin ...

  6. c++11 多线程依次打印ABC

    并发 练习代码 #include <thread> #include <vector> #include <mutex> #include <iostream ...

  7. 用三个线程按顺序循环打印ABC三个字母

    有两种方法:semaphore信号量和mutex互斥锁.需要注意的是C++11已经没有semaphore. C++ 并发编程(六):信号量(Semaphore) - 止于至善 - SegmentFau ...

  8. Java多线程wait和notify协作,按序打印abc

    有一个经典的多线程面试题:启三个线程,按序打印ABC 上代码: package cn.javaBase.study_thread1; class MyRunnable1 implements Runn ...

  9. 迅雷笔试题 (JAVA多线程)启动三个线程,分别打印A B C,现在写一个程序 循环打印ABCABCABC

    题目:http://wenku.baidu.com/view/d66187aad1f34693daef3e8a.html 启动三个线程,分别打印A B C,现在写一个程序 循环打印ABCABCABC. ...

随机推荐

  1. gentoo use-flag 全局标识 大全 (官方搬运) 英文 适用funtoo

    连接 https://www.gentoo.org/support/use-flags/ 提示 ctrl+F 可在页面查找 搬运 Global USE flags FlagDescription 3d ...

  2. 在浏览器输入 URL 回车之后发生了什么

    注意:本文的步骤是建立在,请求的是一个简单的 HTTP 请求,没有 HTTPS.HTTP2.最简单的 DNS.没有代理.并且服务器没有任何问题的基础上. 大致流程 URL 解析 DNS 查询 TCP ...

  3. prometheus 配置项注意事项

    1.job:metrics_path 如果是静态模式下配置job(statics),直接配置job的metrics_path选项是不生效的.需要同时在exporter端指定metrics_path.如 ...

  4. C 全局变量 本地变量

  5. 【转】PS1应用-修改linux终端命令行字体颜色

    原文链接:https://www.jianshu.com/p/4239d3ea72fe cd ls -la vim .bashrc 在.bashrc中加入这一行: PS1="\[\e[37; ...

  6. Ubuntu系统---C++之Eclipse IDE 编译器安装

    Ubuntu系统---C++之Eclipse IDE 编译器安装 Eclipse是一个基于Java的.开放源码的.可扩展的应用开发平台,它为编程人员提供了一流的Java集成开发环境(Integrate ...

  7. 如果将 macOS Mojave 降级为 macOS Sierra 或者更低版本

    当前系统是10.14,我想装回10.11 办法: 1. 下载10.11, 我是从themacgo网站下载的 https://themacgo.com/macos-sierra-10-12-1-dmg- ...

  8. WCF Endpoint分类

    WCF中可以为一个Service配置多个Endpoint 这些Endpoint的分类方法有下面3中 1.全局就一个endpoint,一个接口公开所有的方法,这适合简单的业务场景 2.将endpoint ...

  9. vue1 动态组件

  10. 前端知识体系:JavaScript基础-原型和原型链-理解 es6 中class构造以及继承的底层实现原理

    理解 es6 中class构造以及继承的底层实现原理 原文链接:https://blog.csdn.net/qq_34149805/article/details/86105123 1.ES6 cla ...