主要是利用线程的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. jQuery动画速成

    引入下面css中样式,然后在需要使用的元素中类上添加相应的效果就可以了 例如 animated固定要添加的类,不然会没有效果,bounceIn是你想要的动画效果,fight是你自己定义的类名,可以写样 ...

  2. php获取客户机mac地址

    @exec("arp -a",$array); //执行arp -a命令,结果放到数组$array中 foreach($array as $value){ //匹配结果放到数组$m ...

  3. List · leetcode-24. 交换相邻节点

    题面 Given a linked list, swap every two adjacent nodes and return its head. You may not modify the va ...

  4. flask中重定向所涉及的反推:由视图函数反推url

    flask中重定向所涉及的反推:由视图函数反推url 例如有视图index() 反推 url的/default # -*- coding: utf-8 -*- from flask import Fl ...

  5. 【OGG 故障处理】OGG-01028

    通过ATSCN 的方式启动REPLICAT 进程的时候报错 GGSCI> START REPLICAT RP_XXXX1, ATCSN 15572172378 GGSCI> VIEW RE ...

  6. kernel源代码标记:mainline 、longterm、stable、linux-next、snapshot的含义

    mainline .longterm.stable.linux-next.snapshot这些名词,都是linux kernel source的标记名称,可以理解为代号. mainline mainl ...

  7. linux修改文件系统注册设备

  8. C++——namespace

    scope和namespace scope就是我们常说的作用域,namespace是C++引入的一个关键字.这两种都和作用域有些微妙的联系,下面 引自Global scope vs global na ...

  9. 第一课 IP通信

       我们的专业课:<IP通信>开课了.    在第一节课,我们初步了解了关于通信的知识,涨了知识,下面我就说一下第一节课所学所感.    在学习这门课的时候,需要我们认真预习,认真听课, ...

  10. python基础应用---列表应用

    列表:列表用[]来表示 names = ['wang', 'yuan', 'yang', 'china', 'french', 'wang'] #列表增加 names.append('zhang') ...