使用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();
}
} }

使用Java实现三个线程交替打印0-74的更多相关文章

  1. 多线程下,两个线程交替打印0 -100,使用wait()和notify()

    多线程下,两个线程交替打印0 -100,使用wait()和notify() public class ThreadTest{ private static final Object lock = ne ...

  2. 使用Java线程并发库实现两个线程交替打印的线程题

    背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题.晚上闲着没事就决定把它实现出来. 题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交 ...

  3. Java中多个线程交替循环执行

    有些时候面试官经常会问,两个线程怎么交替执行呀,如果是三个线程,又怎么交替执行呀,这种问题一般人还真不一定能回答上来.多线程这块如果理解的不好,学起来是很吃力的,更别说面试了.下面我们就来剖析一下怎么 ...

  4. Java并发 两个线程交替执行和死锁

    今天看到一个题:两个线程交替打印奇数和偶数,即一个线程打印奇数,另一个打印偶数,交替打印从1到100.想了下有多重实现方法. wait和notify方法: public class OddEven { ...

  5. java实现线程交替打印1-52和A-Z

    题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交替打印,输出结果为12A34B...........5152Z. 3.请用多线程方式实现. 实现思路:通过锁(s ...

  6. 斐讯面试记录—三线程交替打印ABC

    package cn.shenzhen.feixun; public class PrintABC extends Thread{ private String name; private Objec ...

  7. java Semaphore实现ABC三个线程循环打印

    Semaphore位于java.util.concurrent包下.其中有两个重要的方法acquire()和release().acquire用来获取一个信号量,并且是阻塞型的,如果当前还有可用的信号 ...

  8. java启动3个线程轮流打印数字

    转自:http://blog.csdn.net/u014011112/article/details/50988769 http://blog.csdn.net/perrywork/article/d ...

  9. java多线程三之线程协作与通信实例

    多线程的难点主要就是多线程通信协作这一块了,前面笔记二中提到了常见的同步方法,这里主要是进行实例学习了,今天总结了一下3个实例: 1.银行存款与提款多线程实现,使用Lock锁和条件Condition. ...

随机推荐

  1. Sentinel :微服务哨兵

    1. Sentinel 是什么? 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性. Sentin ...

  2. MySQL 物理备份工具-xtrabackup

    安装 wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo yum -y install perl ...

  3. Spring Boot2 系列教程 (十一) | 整合数据缓存 Cache

    如题,今天介绍 SpringBoot 的数据缓存.做过开发的都知道程序的瓶颈在于数据库,我们也知道内存的速度是大大快于硬盘的,当需要重复获取相同数据时,一次又一次的请求数据库或者远程服务,导致大量时间 ...

  4. 失衡天平 - 简单dp

    链接:https://www.nowcoder.com/acm/contest/186/C来源:牛客网 终于Alice走出了大魔王的陷阱,可是现在傻傻的她忘了带武器了,这可如何是好???这个时候,一个 ...

  5. ELK学习实验018:filebeat收集docker日志

    Filebeat收集Docker日志 1 安装docker [root@node4 ~]# yum install -y yum-utils device-mapper-persistent-data ...

  6. Oracle GoldenGate Best Practices: Active-Active Configuration with DML Auto CDR

    Executive Overview This document is an introduction to Oracle GoldenGate (DIPC remote agent)’s best ...

  7. Nmap使用教程(一)

    基本扫描技术 扫描单个网络 nmap 192.168.1.1/www.baidu.com 扫描多个网络/目标 nmap 192.168.1.1 192.168.1.2 #将扫描同个网段内不同的ip地址 ...

  8. shell脚本快速配置yum源

    我们在使用Red Hat系列的Linux系统时经常要配置yum源,本文档提出一个快速配置yum源的方法,就是用shell脚本来实现. 我们在使用Red Hat系列的Linux系统时经常要配置yum源, ...

  9. # 团队项目-Beta冲刺2(七个小矮人)

    团队项目-Beta冲刺2(七个小矮人) 一.格式描述 这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/GeographicInformationScien ...

  10. 什么是C/S结构,其和B/S有什么区别很联系呢

    什么是C/S结构,其和B/S有什么区别很联系呢 原地址:https://zhidao.baidu.com/question/12962713.html C/S结构即服务器/客户机结构.C/S结构通常采 ...