java多线程循环_Java多线程循环打印ABC的5种实现方法

本文介绍了5种使用Java实现多线程循环打印ABC的方案:1) Synchronized同步法,2) Lock锁方法,3) ReentrantLock结合Condition,4) AtomicInteger方法,5) Semaphore信号量方式。每种方法详细阐述了实现思路和代码示例,展示了不同并发控制手段在解决线程同步问题上的应用。
摘要由CSDN通过智能技术生成

题目:3个线程循环打印ABC,其中A打印3次,B打印2次,C打印1次,循环打印2轮

一.Synchronized同步法

思路:使用synchronized、wait、notifyAll的方法利用线程标记变量控制三个线程的执行顺序。

/**

* @author XDarker

* 2018-5-17

*/

public class Main {

public static void main(String[] args) throws InterruptedException {

int num = 1;//当前正在执行线程的标记

ABCPrint print = new ABCPrint(num);

Thread threadA = new Thread(new RunnableA(print));

Thread threadB = new Thread(new RunnableB(print));

Thread threadC = new Thread(new RunnableC(print));

threadA.start();

Thread.sleep(500);

threadB.start();

Thread.sleep(500);

threadC.start();

}

}

class RunnableA implements Runnable{

private ABCPrint print;

public RunnableA(ABCPrint print) {

super();

this.print = print;

}

@Override

public void run() {

print.PrintA();

}

}

class RunnableB implements Runnable{

private ABCPrint print;

public RunnableB(ABCPrint print) {

super();

this.print = print;

}

@Override

public void run() {

print.PrintB();

}

}

class RunnableC implements Runnable{

private ABCPrint print;

public RunnableC(ABCPrint print) {

super();

this.print = print;

}

@Override

public void run() {

print.PrintC();

}

}

class ABCPrint {

private int num;//当前正在执行线程的标记

public ABCPrint(int num) {

super();

this.num = num;

}

public void PrintA(){

for (int j = 0; j < 2; j++)//表示 循环打印2轮

synchronized(this){

while(num != 1){

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

for (int i = 0; i < 3; i++) {//表示 打印3次

System.out.println("A");

}

//打印A线程执行完 ,通知打印B线程

num = 2;

this.notifyAll();

}

}

public void PrintB(){

for (int j = 0; j < 2; j++)//表示 循环打印2轮

synchronized(this){

while(num != 2){

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

for (int i = 0; i < 2; i++) {//表示 打印2次

System.out.println("B");

}

//打印B线程执行完 ,通知打印C线程

num = 3;

this.notifyAll();

}

}

public void PrintC(){

for (int j = 0; j < 2; j++)//表示 循环打印2轮

synchronized(this){

while(num != 3){

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println("C");

//打印C线程执行完 ,通知打印A线程

num = 1;

this.notifyAll();

}

}

}

二.Lock锁方法

思路:Lock锁机制是JDK 5之后新增的锁机制,不同于内置锁,Lock锁必须显式声明,并在合适的位置释放锁。Lock是一个接口,通过ReentrantLock具体实现进行显式的锁操作,即获取锁和释放锁。

/**

* @author XDarker

* 2018-5-17

*/

public class Main {

public static void main(String[] args) throws InterruptedException {

int num = 1;//当前正在执行线程的标记

ABCPrint print = new ABCPrint(num);

Thread threadA = new Thread(new RunnableA(print));

Thread threadB = new Thread(new RunnableB(print));

Thread threadC = new Thread(new RunnableC(print));

threadA.start();

Thread.sleep(500);

threadB.start();

Thread.sleep(500);

threadC.start();

}

}

class RunnableA implements Runnable{

private ABCPrint print;

public RunnableA(ABCPrint print) {

super();

this.print = print;

}

@Override

public void run() {

print.PrintA();

}

}

class RunnableB implements Runnable{

private ABCPrint print;

public RunnableB(ABCPrint print) {

super();

this.print = print;

}

@Override

public void run() {

print.PrintB();

}

}

class RunnableC implements Runnable{

private ABCPrint print;

public RunnableC(ABCPrint print) {

super();

this.print = print;

}

@Override

public void run() {

print.PrintC();

}

}

class ABCPrint {

private static final Lock lock = new ReentrantLock();//通过JDK5中的Lock锁来保证线程的访问的互斥

private int num;//当前正在执行线程的标记

public ABCPrint(int num) {

super();

this.num = num;

}

public void PrintA(){

for (int j = 0; j < 2;)//表示 循环打印2轮

try {

lock.lock();

while(num == 1){

for (int i = 0; i < 3; i++) {//表示 打印3次

System.out.println("A");

}

//打印A线程执行完 ,通知打印B线程

num = 2;

j++;

}

}finally{//调用了lock方法后,需在finally(finally确保一定会执行,除非执行了exit方法)语句里调用unlock方法。否则会造成死锁等问题

lock.unlock();

}

}

public void PrintB(){

for (int j = 0; j < 2;)//表示 循环打印2轮

try{

lock.lock();

while(num == 2){

for (int i = 0; i < 2; i++) {//表示 打印2次

System.out.println("B");

}

//打印B线程执行完 ,通知打印C线程

num = 3;

j++;

}finally{

lock.unlock();

}

}

public void PrintC(){

for (int j = 0; j < 2;)//表示 循环打印2轮

try{

lock.lock();

while(num == 3){

System.out.println("C");

//打印C线程执行完 ,通知打印A线程

num = 1;

j++;

}

}finally{

lock.unlock();

}

}

}

三.ReentrantLock结合Condition

思路:Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法。Condition它更强大的地方在于:能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition。

/**

* @author XDarker

* 2018-5-17

*/

public class Main{

public static void main(String[] args) {

final AlternateDemo ad = new AlternateDemo();

new Thread(new Runnable() {

@Override

public void run() {

for (int i = 0; i < 2; i++) {

ad.loopA(i);

}

}

},"A").start();

new Thread(new Runnable() {

@Override

public void run() {

for (int i = 0; i < 2; i++) {

ad.loopB(i);

}

}

},"B").start();

new Thread(new Runnable() {

@Override

public void run() {

for (int i = 0; i < 2; i++) {

ad.loopC(i);

}

}

},"C").start();

}

}

class AlternateDemo{

private int num = 1;//当前正在执行线程的标记

private Lock lock = new ReentrantLock();

private Condition condition1 = lock.newCondition();

private Condition condition2 = lock.newCondition();

private Condition condition3 = lock.newCondition();

public void loopA(int loop){

lock.lock();

try {

//1.判断

if(num != 1){

condition1.await();

}

//2.打印

for (int i = 0; i < 3; i++) {

System.out.println(Thread.currentThread().getName()+"-"+"第"+loop+"轮"+"-第"+i+"次");

}

//3.唤醒

num = 2;

condition2.signal();

} catch (Exception e) {

// TODO: handle exception

}finally{

lock.unlock();

}

}

public void loopB(int loop){

lock.lock();

try {

//1.判断

if(num != 2){

condition2.await();

}

//2.打印

for (int i = 0; i < 2; i++) {

System.out.println(Thread.currentThread().getName()+"-"+"第"+loop+"轮"+"-第"+i+"次");

}

//3.唤醒

num = 3;

condition3.signal();

} catch (Exception e) {

// TODO: handle exception

}finally{

lock.unlock();

}

}

public void loopC(int loop){

lock.lock();

try {

//1.判断

if(num != 3){

condition3.await();

}

//2.打印

for (int i = 0; i < 1; i++) {

System.out.println(Thread.currentThread().getName()+"-"+"第"+loop+"轮"+"-第"+i+"次");

}

System.out.println("---------------------------");

//3.唤醒

num = 1;

condition1.signal();

} catch (Exception e) {

// TODO: handle exception

}finally{

lock.unlock();

}

}

}

四.AtomicInteger方法

思路:AtomicInteger,一个提供原子操作的Integer的类。在Java中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。

/**

* @author XDarker

* 2018-5-17

*/

public class Main {

public static void main(String[] args) {

new ABCPrint("A",3).start();//A打印3次

new ABCPrint("B",2).start();//B打印2次

new ABCPrint("C",1).start();//C打印1次

}

}

class ABCPrint extends Thread {

//打印次数

private int count;

private final String str[] = { "A", "B", "C" };

private final static AtomicInteger atomCount= new AtomicInteger();

public ABCPrint(String name,int count) {

this.setName(name);

this.count = count;

}

@Override

public void run() {

while (true) {

// 循环满2轮退出打印

if (atomCount.get() / 3 == 2) {

break;

}

synchronized (atomCount) {

// 顺序打印A、B、C

if (str[atomCount.get() % 3].equals(getName())) {

atomCount.getAndIncrement();//自增

//对应打印几次

for (int i = 0; i < count; i++) {

System.out.println(getName());

}

//表示一轮打印结束 方便观察打印下分隔符

if ("C".equals(getName())) {

System.out.println("================================");

}

// 当前线程打印打印完成后唤醒其它线程

atomCount.notifyAll();

} else {

// 非顺序线程wait()

try {

atomCount.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

}

五.Semaphore信号量方式

思路: 信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。Semaphore线程同步机制,当调用acquire()时,内部计数器数值增加;调用release()时,内部计数器递减;计数器值不能小于0,如果等于0,acquire()方法被阻塞,需要等待其他线程调用release()方法。

/**

* @author XDarker

* 2018-5-17

*/

public class Main {

public static void main(String[] args) throws InterruptedException {

new ThreadA(3).start();

new ThreadB(2).start();

new ThreadC(1).start();

}

//以A开始的信号量,初始信号量数量为1

private static Semaphore A = new Semaphore(1);

//B、C信号量,A完成后开始,初始信号数量为0

private static Semaphore B = new Semaphore(0);

private static Semaphore C = new Semaphore(0);

static class ThreadA extends Thread {

private int count;

public ThreadA(int count) {

super();

this.count = count;

}

@Override

public void run() {

try {

for (int i = 0; i < 2; i++) {

A.acquire();// A获取信号执行,A信号量减1,当A为0时将无法继续获得该信号量

for (int j = 0; j < count; j++) {

System.out.print("A");

}

B.release();// B释放信号,B信号量加1(初始为0),此时可以获取B信号量

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

static class ThreadB extends Thread {

private int count;

public ThreadB(int count) {

super();

this.count = count;

}

@Override

public void run() {

try {

for (int i = 0; i < 2; i++) {

B.acquire();

for (int j = 0; j < count; j++) {

System.out.print("B");

}

C.release();

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

static class ThreadC extends Thread {

private int count;

public ThreadC(int count) {

super();

this.count = count;

}

@Override

public void run() {

try {

for (int i = 0; i < 2; i++) {

C.acquire();

for (int j = 0; j < count; j++) {

System.out.println("C");

}

A.release();

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

原始文地址:https://blog.csdn.net/weixin_39723337/article/details/80352783

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值