题目描述

建立三个线程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. SpringBoot 整合RabbitMQ错误记录

    1. 控制台报错:Exception in thread "main" java.io.IOException…… Caused by: com.rabbitmq.client.S ...

  2. nginx的6种负载均衡策略

    在服务器集群中,Nginx起到一个反向代理服务器的作用.为了避免单独一个服务器压力过大导致服务器奔溃,就需要将不同用户的请求转发给不同给不同的服务器,保证集群中的每一台服务器都能正常运作,这种机制就叫 ...

  3. tsconfig.json配置项详解

    { "compilerOptions": { "allowUnreachableCode": true, // 不报告执行不到的代码错误. "allo ...

  4. IDA分析时添加新的C语言结构体

    View - Open Subviews - Local Type - INSERT键 - 输入新结构体 - 右击"Synchornize to idb" 之后再分析处按 T 就可 ...

  5. VMware与 Device/Credential Guard 不兼容,解决办法及心得

    以下为心路历程,想要直接解决可以直接拉到最后看后续 百度要你取消Hyper-V功能,但我要用docker,以及一些相关的帖子都无效的情况下 https://blog.csdn.net/u0136677 ...

  6. Restful API接口规范

    1. 域名 应该尽量将API部署在专用域名之下. https://api.example.com 如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下. https://example.org ...

  7. ztree选父不选子选子不选父

    var setting = { data: { simpleData: { enable: true } } ,check: { enable: true , chkStyle: 'checkbox' ...

  8. CI/CD DevOps

    CI/CD DevOps 通过技术工具链完成持续集成CI.持续交付CD.用户反馈和系统优化的整合,实现跨团队的无缝协作(DevOps). 什么是持续集成? 他是开发每天代码更新的副本,所有的开发工作都 ...

  9. Python列表操作与深浅拷贝(5)——数字处理函数、类型判断、列表链表队列栈

    python内建数据结构 分类 数值型: int float complex bool 序列对象: 字符串str 列表list 元组tuple 键值对: 集合set 字典dict 数值型 (list ...

  10. Skyshop.代码解析

    MarmosetInput.cginc: Input结构定义: struct Input { #if defined(MARMO_PACKED_UV) || defined(MARMO_PACKED_ ...