问题:

有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. USBDM Debugger interface for Freescale RS08,HCS08,HCS12,Coldfire and ARM-Kinetis Devices.

    Introduction USBDM is a debugger hardware interface for a range of Freescale microcontrollers. It is ...

  2. 【Go命令教程】11. go vet 与 go tool vet

    命令 go vet 是一个 用于检查 Go 语言源码中静态错误的简单工具.与大多数 Go 命令一样,go vet 命令可以接受 -n 标记和 -x 标记.-n 标记用于只打印流程中执行的命令而不真正执 ...

  3. mybatis 详解

    http://www.cnblogs.com/ysocean/category/1007230.html

  4. [Asp.net]web.config customErrors 如何设置?

    摘要 customErrors也经常在开发部署中看到<customErrors mode="Off" />,设置这样可以在页面上看到详细的错误信息.但也为黑客提供了攻击 ...

  5. MORMOT的数据序列

    MORMOT的数据序列 mormot服务器回复客户端通过Ctxt.OutContent属性. 此属性的类型是:SockString.   // property OutContent: SockStr ...

  6. ios 向sqlite数据库插入和读取图片数据

    向sqlite数据库插入和读取图片数据 (for ios) 假定数据库中存在表 test_table(name,image), 下面代码将图片文件test.png的二进制数据写到sqlite数据库: ...

  7. C#使用ProtocolBuffer(ProtoBuf)进行Unity中的Socket通信

    首先来说一下本文中例子所要实现的功能: 基于ProtoBuf序列化对象 使用Socket实现时时通信 数据包的编码和解码 下面来看具体的步骤: 一.Unity中使用ProtoBuf 导入DLL到Uni ...

  8. Linux学习15-CentOS安装mysql5.6环境

    前言 在linux上安装mysql5.6版本,并远程连接mysql数据库操作 安装mysql mysql的安装可以用yum安装更方便 [root@yoyo ~]# cd /usr/local/ [ro ...

  9. 每天一个linux命令:df 命令

    linux中df命令的功能是用来检查linux服务器的文件系统的磁盘空间占用情况.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 1.命令格式: df [选项] [文件] 2.命 ...

  10. 女子监狱第一季/全集Orange Is the New Black迅雷下载

    本季第一季 Orange Is the New Black 1 (2013) 看点:该剧描述主人公Piper Chapman(Taylor Schilling)在大学里结识了毒贩Alex(Laura ...