问题:

有a、b、c三个线程,使得它们按照abc依次执行10次。

实现:

package com.dx.juc.test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class ABC {
public static void main(String[] args) {
final AlternateDemo alternateDemo=new AlternateDemo(); new Thread(new Runnable() {
public void run() {
for(int i=1;i<10;i++){
alternateDemo.loopA(i);
}
}
}, "A").start(); new Thread(new Runnable() {
public void run() {
for(int i=1;i<10;i++){
alternateDemo.loopB(i);
}
}
}, "B").start(); new Thread(new Runnable() {
public void run() {
for(int i=1;i<10;i++){
alternateDemo.loopC(i);
System.out.println("---------------------------------------");
}
}
}, "C").start();
}
} class AlternateDemo {
private Lock lock = new ReentrantLock(); private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition(); // 一个标号,标记当前可以执行的线程编号.1-a线程可以执行,2-b线程可以执行,3-c线程可以执行。
private int flag = 1; public void loopA(int loopNum) {
lock.lock(); try {
// 1)等待喚醒
// 如果flag标记值不是1的话,就让线程处于等待状态,直到其他线程唤醒它。
if (flag != 1) {
conditionA.await();
} // 2)被喚醒后,開始執行。
for (int i = 1; i <= 1; i++) {
System.out.println(Thread.currentThread().getName() + "-" + loopNum + "-" + i);
} // 3)修改標記flag,并喚醒下一個線程。
flag = 2;
conditionB.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void loopB(int loopNum) {
lock.lock(); try {
// 1)等待喚醒
// 如果flag标记值不是2的话,就让线程处于等待状态,直到其他线程唤醒它。
if (flag != 2) {
conditionB.await();
} // 2)被喚醒后,開始執行。
for (int i = 1; i <= 1; i++) {
System.out.println(Thread.currentThread().getName() + "-" + loopNum + "-" + i);
} // 3)修改標記flag,并喚醒下一個線程。
flag = 3;
conditionC.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void loopC(int loopNum) {
lock.lock(); try {
// 1)等待喚醒
// 如果flag标记值不是3的话,就让线程处于等待状态,直到其他线程唤醒它。
if (flag != 3) {
conditionC.await();
} // 2)被喚醒后,開始執行。
for (int i = 1; i <= 1; i++) {
System.out.println(Thread.currentThread().getName() + "-" + loopNum + "-" + i);
} // 3)修改標記flag,并喚醒下一個線程。
flag = 1;
conditionA.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}

测试打印结果:

A-1-1
B-1-1
C-1-1
---------------------------------------
A-2-1
B-2-1
C-2-1
---------------------------------------
A-3-1
B-3-1
C-3-1
---------------------------------------
A-4-1
B-4-1
C-4-1
---------------------------------------
A-5-1
B-5-1
C-5-1
---------------------------------------
A-6-1
B-6-1
C-6-1
---------------------------------------
A-7-1
B-7-1
C-7-1
---------------------------------------
A-8-1
B-8-1
C-8-1
---------------------------------------
A-9-1
B-9-1
C-9-1
---------------------------------------

更多实现方案:

请参考《Java:现有线程T1/T2/T3,如何确保T1执行完成之后执行T2,T3在T2执行完成之后执行。》

Java-JUC(十):线程按序交替执行的更多相关文章

  1. JUC-Condition和Lock实践-线程按序交替执行

    编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A.B.C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示.如:ABCABCABC…… 依次递归 这里只使用c ...

  2. java 面试题 -- 线程 按序 交替

    编写一个程序,开启 3 个线程,这三个线程的 ID 分别为A.B.C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示.如:ABCABCABC…… 依次递归? packag ...

  3. Java并发编程(二)如何保证线程同时/交替执行

    第一篇文章中,我用如何保证线程顺序执行的例子作为Java并发系列的开胃菜.本篇我们依然不会有源码分析,而是用另外两个多线程的例子来引出Java.util.concurrent中的几个并发工具的用法. ...

  4. 深入理解Java虚拟机(十)——线程安全与锁优化

    什么是线程安全 当多个线程同时访问一个对象的时候,不需要考虑什么额外的操作就能获取正确的值,就是线程安全的. 线程安全的程度 1.不可变 不可变的对象一定是线程安全的,因为值始终只有一个. final ...

  5. Java两个线程实现交替运行-以交替打印奇偶数为例

    本文旨在两个线程交替运行,不多哔哔直接看代码吧 public class Work2 { static final Object object = new Object(); public stati ...

  6. 【Java并发】线程的顺序执行

    /** * 问题:有线程a.b.c,如何让它们顺序执行? * 方式一:可用Join()方法实现 * 方式二:可用newSingleThreadExecutor() * Created by Smile ...

  7. (三)juc高级特性——虚假唤醒 / Condition / 按序交替 / ReadWriteLock / 线程八锁

    8. 生产者消费者案例-虚假唤醒 参考下面生产者消费者案例: /* * 生产者和消费者案例 */ public class TestProductorAndConsumer { public stat ...

  8. Java Juc学习笔记

    Java JUC 简介 在 Java 5.0 提供了 java.util.concurrent (简称JUC )包,在此包中增加了在并发编程中很常用的实用工具类,用于定义类似于线程的自定义子系统,包括 ...

  9. Java并发编程——线程安全及解决机制简介

    简介: 本文主要介绍了Java多线程环境下,可能会出现的问题(线程不安全)以及相应的解决措施.通过本文,你将学习到如下几块知识: 1. 为什么需要多线程(多线程的优势) 1. 多线程带来的问题—线程安 ...

随机推荐

  1. 应用通信-方案一:RestTemplate

    @RestController public class ClientController { @Autowired private LoadBalancerClient loadBalancerCl ...

  2. 接口开发-集成数据库操作(mybatis)

    关于数据存储,最常用的方式就是存到数据库,此篇以MySQL数据库为例,以mybatis框架完成数据库的操作. 一.添加对应依赖 <!-- 数据库:MySQL --> <depende ...

  3. 关于eclipse的indigo版中文注释时字体太小的问题(转)

    eclipse目前最新版代号indigo, 在win7上使用时中文注释时字体太小的问题. 为什么会这样? 首先我们应该知道, 在win7系统中, font是有"显示"和" ...

  4. HDU 3472 HS BDC (混合图的欧拉路径判断)

    HS BDC Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  5. RC4加密算法的原理及实现

    RC4于1987年提出,和DES算法一样.是一种对称加密算法,也就是说使用的密钥为单钥(或称为私钥). 但不同于DES的是.RC4不是对明文进行分组处理,而是字节流的方式依次加密明文中的每个字节.解密 ...

  6. STM32F103ZET6 用定时器级联方式输出特定数目的PWM

    STM32F103ZET6 用定时器级联方式输出特定数目的PWM STM32F103ZET6里共有8个定时器,其中高级定时器有TIM1-TIM5.TIM8,共6个. 这里需要使用定时器的级联功能,ST ...

  7. In order to use an interrupt in a Cortex-M3/M4, you need the following

    a stack. The core automatically saves several registers on the stack when an interrupt fires. Initia ...

  8. Revit MEP API找到连接器连接的连接器

    通过conn.AllRefs;可以找到与之连接的连接器. //连接器连接的连接器 [TransactionAttribute(Autodesk.Revit.Attributes.Transaction ...

  9. 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查

    AngularJS中的$resource服务相比$http服务更适合与RESTful服务进行交互.本篇后端使用ASP.NET Web API, 前端使用$resource,实现增删改查. 本系列包括: ...

  10. Convolutional Neural Networks at Constrained Time Cost(精读)

    一.文献名字和作者     Convolutional Neural Networks at Constrained Time Cost,CVPR 2015 二.阅读时间      2015年6月30 ...