java多线程交替打印_使用Java实现三个线程交替打印0-74

本文讲解了如何使用Java的ReentrantLock和Condition接口实现三个线程按照0-1-2的顺序交替打印数字0-74。通过创建三个互斥条件变量,确保线程间的同步和顺序执行。关键在于理解信号和等待机制,以及如何利用环形队列控制线程唤醒和阻塞。
摘要由CSDN通过智能技术生成

使用Java实现三个线程交替打印0-74

题目分析

三个线程交替打印,即3个线程是按顺序执行的。一个线程执行完之后,唤醒下一个线程,然后阻塞,等待被该线程的上一个线程唤醒。执行的顺序是一个环装的队列 0->1->2->0 ....->0->1->2

实现思路

由于三个线程一次只能有一个在打印数字,所以需要用一个锁来进行同步。但是在打印时要保证顺序就要求 一个线程打印完之后只能唤醒它的下一个线程,而不是唤醒所有的线程。这就要求给每一个线程都有一个自己的状态来控制阻塞和唤醒。

java 并发包中的锁(实现了Lock接口的ReentrantLock、ReentrantReadWriteLock)有一个newCondition方法。调用该方法会返回与该锁绑定Condition对象实例。当线程获取锁之后,调用Condition实例的await方法会自动释放线程的锁,当其他线程调用该Condition对象实例的signal方法后,该线程会自动尝试获取锁。

通过对Condition的分析可知,我们只要对三个线程生成三个Condition对象。当一个线程打印一个数字之后就调用下一个线程的Condition对象的signal方法唤醒下一个线程,然后调用自己的Condition的await线程进入等待状态。这样就实现了线程执行顺序的控制。由于线程的执行是一个环形的队列,我们用一个数组存放每个线程的Condition对象,通过对下标加一然后取模来实现环形队列。

代码

package com.test.concurrent.alternatingprint;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

public class PrintNumber extends Thread {

/**

* 多个线程共享这一个sequence数据

*/

private static int sequence=0;

private static final int SEQUENCE_END =75;

private Integer id;

private ReentrantLock lock;

private Condition[] conditions;

private PrintNumber(Integer id, ReentrantLock lock, Condition[] conditions) {

this.id = id;

this.setName("thread" + id);

this.lock = lock;

this.conditions = conditions;

}

@Override

public void run() {

while (sequence >= 0 && sequence < SEQUENCE_END) {

lock.lock();

try {

//对序号取模,如果不等于当前线程的id,则先唤醒其他线程,然后当前线程进入等待状态

while (sequence % conditions.length != id) {

conditions[(id + 1) % conditions.length].signal();

conditions[id].await();

}

System.out.println(Thread.currentThread().getName() + " " + sequence);

//序号加1

sequence = sequence + 1;

//唤醒当前线程的下一个线程

conditions[(id + 1) % conditions.length].signal();

//当前线程进入等待状态

conditions[id].await();

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

//将释放锁的操作放到finally代码块中,保证锁一定会释放

lock.unlock();

}

}

//数字打印完毕,线程结束前唤醒其余的线程,让其他线程也可以结束

end();

}

private void end() {

lock.lock();

conditions[(id + 1) % conditions.length].signal();

conditions[(id + 2) % conditions.length].signal();

lock.unlock();

}

public static void main(String[] args) {

int threadCount = 3;

ReentrantLock lock = new ReentrantLock();

Condition[] conditions = new Condition[threadCount];

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

conditions[i] = lock.newCondition();

}

PrintNumber[] printNumbers = new PrintNumber[threadCount];

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

PrintNumber p = new PrintNumber(i, lock, conditions);

printNumbers[i] = p;

}

for (PrintNumber printNumber : printNumbers) {

printNumber.start();

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值