题目描述

建立三个线程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. C#中文转换为拼音NPinyin代码【转】

    项目地址:https://code.google.com/p/npinyin/ 在一个采集的程序中,为了给每个文章起一个别名,据说有很好的别名的话,对于百度.google的收录 是很有好处的.按照Se ...

  2. 【转】asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程

    最近在学习张善友老师的NanoFabric 框架的时了解到Exceptionless : https://exceptionless.com/ !因此学习了一下这个开源框架!下面对Exceptionl ...

  3. CentOS安装etcd和flannel实现Docker跨物理机通信

    1.安装etcd yum install etcd systemctl stop etcd systemctl start etcd systemctl status etcd systemctl e ...

  4. App_Code下类无法引用问题

    App_Code 下创建的.cs文件仅仅是“内容”不是代码.设置文件为“编译”就可正常引用.

  5. Winform的控件以及DataGridView的一般使用

    先上学习测试的一些截图 1:获取多个控件上面的值(checkbox,combobox,textbox,radiobutton) 2:获取到选择行的主键ID的value,方便我们进一步CURD 3:获取 ...

  6. AD读取Excel新建客户邮箱的测试环境部署有感

    现有AD的账户操作所有服务几乎用WebApi方式,此 方法是便于搭建和部署,做到了前后端的分离 ,其中验证Exchange邮箱转发模块时发现foxmail的exchange本地邮箱配置极其简单,以此记 ...

  7. VMware基本用法

    ###VMware tools 介绍 只有在VMware虚拟机中安装好了VMware Tools,才能实现主机与虚拟机之间的文件共享,同时可支持自由拖拽的功能,鼠标也可在虚拟机与主机之前自由移动(不用 ...

  8. Ubuntu19.04安装常用软件

    安装Indicator Stickynotes 桌面便签小工具sudo add-apt-repository ppa:umang/indicator-stickynotessudo apt-get u ...

  9. [TCP/IP]TCP服务端accept发生在三次握手的哪一个阶段

    TCP服务端accept发生在三次握手之后 客户端socket()==>connect()==>write()==>read()服务端socket()==>bind()==&g ...

  10. 关于微信小程序中遇到的各种问题汇总(持续更新)

    1.关于 <input />标签容易忽略的问题: 使用<input />标签时容易忘记绑定bindblur()方法(输入框失去焦点时触发),因为用户用键盘输入时不一定会点击完成 ...