题目描述

建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。

5种方法

  1. 使用synchronized, wait和notifyAll
  2. 使用Lock->ReentrantLock 和 state标志
  3. 使用Lock->ReentrantLock 和Condition(await 、signal、signalAll)
  4. 使用Semaphore
  5. 使用AtomicInteger
  6. 扩展:采用join实现(一次性打印)

5.1 使用synchronized, wait和notifyAll

public class ABC7 {
private static Object o = new Object();//所对象
private static int state = 0;//控制顺序
private static int PRINT_NUMBER = 10;//打印次数
private static int THREAD_NUM = 3;//线程数量 static class ThreadGenetic implements Runnable {
char name;
int data;
public ThreadGenetic(char name, int data){
this.name = name;
this.data = data;
}
public void run() {
synchronized (o) {
for(int i = 0; i < PRINT_NUMBER; ) {
if(state % THREAD_NUM == data){//保证顺序
System.out.print(name);
++ state;
i++;//注意保证迭代次数
o.notifyAll();
}else{
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
} public static void main(String[] args) {
new Thread(new ThreadGenetic('B',1)).start();
new Thread(new ThreadGenetic('A',0)).start();
new Thread(new ThreadGenetic('C',2)).start(); } }

5.2 使用Lock->ReentrantLock 和 state标志

import java.util.concurrent.locks.ReentrantLock;

public class ABC {
private static int state = 0;//控制顺序
private static int PRINT_NUMBER = 10;//打印次数
private static int THREAD_NUM = 3;//线程数量
private static ReentrantLock lock = new ReentrantLock();//锁 static class ThreadGenetic extends Thread{
char name;
int data;
public ThreadGenetic(char name, int data){
this.name = name;
this.data = data;
}
public void run(){
for (int i = 0; i < PRINT_NUMBER; ) {//确保打印次数
lock.lock();
if(state % THREAD_NUM == this.data){//确保按顺序打印
System.out.print(this.name);
state++; //确保按顺序打印
i++; //确保打印次数
}
lock.unlock();
}
}
} public static void main(String[] args) {
new ThreadGenetic('B',1).start();
new ThreadGenetic('C',2).start();
new ThreadGenetic('A',0).start();
}
}

5.3 使用Lock->ReentrantLock 和Condition(await 、signal、signalAll)

方法1

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; public class ABC8 {
private static int state = 0;//控制顺序
private static int PRINT_NUMBER = 10;//打印次数
private static int THREAD_NUM = 3;//线程数量
private static ReentrantLock lock = new ReentrantLock();//锁
private static Condition condition = lock.newCondition(); static class ThreadGenetic extends Thread{
char name;
int data;
public ThreadGenetic(char name, int data){
this.name = name;
this.data = data;
}
public void run(){
lock.lock();
try {
for (int i = 0; i < PRINT_NUMBER; ) {//确保打印次数
while(state % THREAD_NUM != data){//确保按顺序打印
condition.await();
}
System.out.print(name);
state++; //确保按顺序打印
i++; //确保打印次数
condition.signalAll();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
}
} public static void main(String[] args) {
new ThreadGenetic('B',1).start();
new ThreadGenetic('C',2).start();
new ThreadGenetic('A',0).start();
}
}

方法2

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; public class ABC2 {
private static int state = 0;//控制顺序
private static int PRINT_NUMBER = 10;//打印次数
private static int THREAD_NUM = 3;//线程数量
private static ReentrantLock lock = new ReentrantLock();//锁
private static Condition conditionA = lock.newCondition();
private static Condition conditionB = lock.newCondition();
private static Condition conditionC = lock.newCondition(); static class ThreadGenetic extends Thread{
char name;
int data;
Condition condition1;
Condition condition2;
public ThreadGenetic(char name, int data, Condition condition1,Condition condition2){
this.name = name;
this.data = data;
this.condition1 = condition1;
this.condition2 = condition2;
}
public void run(){
lock.lock();
try {
for (int i = 0; i < PRINT_NUMBER; ) {//确保打印次数
while(state % THREAD_NUM != data){//确保按顺序打印
condition1.await();
}
System.out.print(name);
state++; //确保按顺序打印
i++; //确保打印次数
condition2.signal();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
}
} public static void main(String[] args) {
new ThreadGenetic('B',1,conditionB,conditionC).start();
new ThreadGenetic('C',2,conditionC,conditionA).start();
new ThreadGenetic('A',0,conditionA,conditionB).start();
}
}

5.4 使用Semaphore

import java.util.concurrent.Semaphore;

public class ABC3 {
private static int PRINT_NUMBER = 10;//打印次数
private static Semaphore semaphoreA = new Semaphore(1);
private static Semaphore semaphoreB = new Semaphore(1);
private static Semaphore semaphoreC = new Semaphore(1); static class ThreadGenetic extends Thread{
char name;
int data;
Semaphore semaphore1;
Semaphore semaphore2;
public ThreadGenetic(char name, Semaphore semaphore1,Semaphore semaphore2){
this.name = name;
this.semaphore1 = semaphore1;
this.semaphore2 = semaphore2;
}
public void run(){
for (int i = 0; i < PRINT_NUMBER; i++) {//确保打印次数
try {
semaphore1.acquire();
System.out.print(name);
semaphore2.release();
} catch (InterruptedException e) {
e.printStackTrace();
} }
}
}
public static void main(String[] args) {
try {
semaphoreB.acquire();//保证A先于BC开始
semaphoreC.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
new ThreadGenetic('B',semaphoreB,semaphoreC).start();
new ThreadGenetic('C',semaphoreC,semaphoreA).start();
new ThreadGenetic('A',semaphoreA,semaphoreB).start();
}
}

5.5 使用AtomicInteger

import java.util.concurrent.atomic.AtomicInteger;

public class ABC5 {
private static AtomicInteger atomicinteger = new AtomicInteger(0);
private static final int MAX_SYC_VALUE = 3 * 10; static class ThreadGenetic extends Thread {
char name;
int data; public ThreadGenetic(char name, int data) {
this.name = name;
this.data = data;
} public void run() {
while (atomicinteger.get() < MAX_SYC_VALUE-1) {
if (atomicinteger.get() % 3 == data) {
System.out.print(name);
atomicinteger.getAndIncrement();
}
} }
} public static void main(String[] args) {
new ThreadGenetic('B', 1).start();
new ThreadGenetic('C', 2).start();
new ThreadGenetic('A', 0).start();
}
}

5.6 采用join实现(一次性打印)

public class ABC6 {

    public static void main(String[] args) {
// 线程A
final Thread a = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("A");
}
}); // 线程B
final Thread b = new Thread(new Runnable() {
@Override
public void run() {
try {
// 执行b线程之前,加入a线程,让a线程执行
a.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B");
}
}); // 线程C
final Thread c = new Thread(new Runnable() {
@Override
public void run() {
try {
// 执行c线程之前,加入b线程,让b线程执行
b.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("C");
}
}); // 启动三个线程
a.start();
b.start();
c.start();
}
}

[******] java多线程连续打印abc的更多相关文章

  1. java多线程编程题之连续打印abc的几种解法

    一道编程题如下: 实例化三个线程,一个线程打印a,一个打印b,一个打印c,三个线程同时执行,要求打印出6个连着的abc 题目分析: 通过题意我们可以得出,本题需要我们使用三个线程,三个线程分别会打印6 ...

  2. java多线程编程之连续打印abc的几种解法

    一道编程题如下: 实例化三个线程,一个线程打印a,一个线程打印b,一个线程打印c,三个线程同时执行,要求打印出10个连着的abc. 题目分析: 通过题意我们可以得出,本题需要我们使用三个线程,三个线程 ...

  3. 三线程连续打印ABC

    package test5; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Reentr ...

  4. Java多线程学习(转载)

    Java多线程学习(转载) 时间:2015-03-14 13:53:14      阅读:137413      评论:4      收藏:3      [点我收藏+] 转载 :http://blog ...

  5. 转:关于JAVA多线程同步

    转:http://lanvis.blog.163.com/blog/static/26982162009798422547/ 因为需要,最近关注了一下JAVA多线程同步问题.JAVA多线程同步主要依赖 ...

  6. Java多线程——<一>概述、定义任务

    一.概述 为什么使用线程?从c开始,任何一门高级语言的默认执行顺序是“按照编写的代码的顺序执行”,日常开发过程中写的业务逻辑,但凡不涉及并发的,都是让一个任务顺序执行以确保得到想要的结果.但是,当你的 ...

  7. ***Java多线程发展简史

    http://blog.jobbole.com/28297/ 本文来自四火的博客(@RayChase),由@_Zhijun 推荐 这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的 ...

  8. [转] Java多线程发展简史

    这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从第一个版本开始,在多线程编程方面的大事件和发展脉络有一个描述,并 ...

  9. java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析

    java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...

随机推荐

  1. 从零到一手写基于Redis的分布式锁框架

    1.分布式锁缘由 学习编程初期,我们做的诸如教务系统.成绩管理系统大多是单机架构,单机架构在处理并发的问题上一般是依赖于JDK内置的并发编程类库,如synchronize关键字.Lock类等.随着业务 ...

  2. kali渗透综合靶机(十一)--BSides-Vancouver靶机

    kali渗透综合靶机(十一)--BSides-Vancouver靶机 靶机下载地址:https://pan.baidu.com/s/1s2ajnWHNVS_NZfnAjGpEvw 一.主机发现 1.n ...

  3. 如何查询正在运行的SQL Server agent job

    运行"msdb"系统数据库下的存储过程"dbo.sp_help_job",可以得知现在SQL Server中有多少个正在运行的agent job: USE [m ...

  4. 网格弹簧质点系统模拟(Spring-Mass System by Fast Method)附源码(转载)

    转载:  https://www.cnblogs.com/shushen/p/5311828.html 弹簧质点模型的求解方法包括显式欧拉积分和隐式欧拉积分等方法,其中显式欧拉积分求解快速,但积分步长 ...

  5. 最全面的PS快捷键使用指南(图文演示)

    每次做图的时候都会记错快捷键,很苦恼有木有!!!只能各处搜寻PS快捷键汇总起来,老板再也不会说我作图慢了....... 1.Ctrl+T:自由变形 该快捷键,主要对图层进行旋转.缩放等变形调整,同时可 ...

  6. java 学习 进阶之 一 (线程基础)

    一.线程安全 线程安全的概念:当多个线程访问某一个类(对象或方法)时.这个类始终都能表现出正确的行为那么这个类(对象或方法)就是线程安全的. synchronized:可以在任何对象及方法上加锁,而加 ...

  7. python 的三元操作符

    条件表达式(三元操作符)    1.有了这个三元操作符的条件表达式,你可以使用一条语句来完成下面的条件判断和赋值操作: x,y=4,5 if x<y: temp = x else: temp = ...

  8. vsftpd服务

    vsftpd服务 文件传输协议(file transfer protocol,FTP),基于该协议FTP客户端与服务端可以实现共享文件,上传文件,下载文件.ftp基于TCP协议生成一个虚拟的连接,主要 ...

  9. Delphi-基础(运算符)

    一.运算符 1.变量 2.运算符** 3.表达式 1.变量 变量解释:编程中最小的存储单元(空间),它的空间大小由它在声明时的数据类型决定. 1.1.声明 : 定义一个变量,告诉Delphi一个名字的 ...

  10. Shel脚本-初步入门之《04》

    Shel脚本-初步入门-04 脚本语言的种类 4.脚本语言的种类 4.1 Shell 脚本语言的种类 Shell 脚本语言是弱类型语言(无须定义变量的类型即可使用),在 Unix/Linux 中主要有 ...