使用Java实现三个线程交替打印0-74
使用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的更多相关文章
- 多线程下,两个线程交替打印0 -100,使用wait()和notify()
多线程下,两个线程交替打印0 -100,使用wait()和notify() public class ThreadTest{ private static final Object lock = ne ...
- 使用Java线程并发库实现两个线程交替打印的线程题
背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题.晚上闲着没事就决定把它实现出来. 题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交 ...
- Java中多个线程交替循环执行
有些时候面试官经常会问,两个线程怎么交替执行呀,如果是三个线程,又怎么交替执行呀,这种问题一般人还真不一定能回答上来.多线程这块如果理解的不好,学起来是很吃力的,更别说面试了.下面我们就来剖析一下怎么 ...
- Java并发 两个线程交替执行和死锁
今天看到一个题:两个线程交替打印奇数和偶数,即一个线程打印奇数,另一个打印偶数,交替打印从1到100.想了下有多重实现方法. wait和notify方法: public class OddEven { ...
- java实现线程交替打印1-52和A-Z
题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交替打印,输出结果为12A34B...........5152Z. 3.请用多线程方式实现. 实现思路:通过锁(s ...
- 斐讯面试记录—三线程交替打印ABC
package cn.shenzhen.feixun; public class PrintABC extends Thread{ private String name; private Objec ...
- java Semaphore实现ABC三个线程循环打印
Semaphore位于java.util.concurrent包下.其中有两个重要的方法acquire()和release().acquire用来获取一个信号量,并且是阻塞型的,如果当前还有可用的信号 ...
- java启动3个线程轮流打印数字
转自:http://blog.csdn.net/u014011112/article/details/50988769 http://blog.csdn.net/perrywork/article/d ...
- java多线程三之线程协作与通信实例
多线程的难点主要就是多线程通信协作这一块了,前面笔记二中提到了常见的同步方法,这里主要是进行实例学习了,今天总结了一下3个实例: 1.银行存款与提款多线程实现,使用Lock锁和条件Condition. ...
随机推荐
- 通过例子学习C++(二)最小公倍数
本文是通过例子学习C++的第二篇,通过这个例子可以快速入门c++相关的语法. 题目要求:输入两个整数,求其最小公倍数. 解答方法一:两个数的最小公倍数,是这两个数中的大数,或者是这2个数的倍数中的最小 ...
- 人群密度检测MCNN+CSRnet
MCNN(简单理解): 三列卷积神经网络,分别为大中小三种不同尺度的卷积核,表示为L列(使用大尺度卷积核: 9*9, 7*7, 7*7,7*7), M(使用中等尺度卷积核: 7*7, 5*5, 5*5 ...
- Java 进程占用内存过多,幕后元凶原来是线程太多
那天中午吃饭,一个同事说,那个项目组的人快气死我了,程序有问题,早晨在群里@了他们,到中午才回消息,然后竟然还说他们的程序没有问题,是我们这边调用的太频繁了. 简直想笑. 背景说明 我们当前这个系统和 ...
- 洛谷 UVA11021 Tribles
UVA11021 Tribles 题意翻译 题目大意 一开始有kk种生物,这种生物只能活1天,死的时候有p_ipi的概率产生ii只这种生物(也只能活一天),询问m天内所有生物都死的概率(包括m天前死 ...
- python爬虫——scrapy的使用
本文中的知识点: 安装scrapy scrapy的基础教程 scrapy使用代理 安装scrapy 由于小哥的系统是win7,所以以下的演示是基于windows系统.linux系统的话,其实命令都一样 ...
- margin和 padding 以及 float :left和float :right的介绍
1.margin和padding的介绍 margin是外边距,padding是内边距,用CSS时首先要做的就是把所有标签的margin和padding清空.这样更容易控制布局和兼容浏览器. p li等 ...
- numpy 其它常用方法
一.创建特殊的数组 1.ones() 语法 np.ones(shape, dtype=None) # shape 创建数组的shape # dtype 指定数组的数据类型 例子 import nump ...
- 4、python基础语法
前言:本文主要介绍python的一些基础语法,包括标识符的定义.行和缩进.引号和注释.输入输出.变量的定义. 一.标识符 1.凡是我们自己取的名字,都是标识符. 2.在Python里,标识符由字母.下 ...
- Browser Security-基本概念
URL格式: scheme://[login[:password]@](host_name|host_address)[:port][/hierarchical/path/to/resource[?s ...
- 个人第4次作业—Alpha项目测试
这个作业属于哪个课程 课程链接 这个作业要求在哪里 作业要求 团队名称 CTRL_IKUN(团队博客) 这个作业的目标 对非本小组的三个项目进行软件测试 一.测试人员个人信息 学号 201731032 ...