LeetCode 按序打印
第1114题
我们提供了一个类:
public class Foo {
public void one() { print("one"); }
public void two() { print("two"); }
public void three() { print("three"); }
}
三个不同的线程将会共用一个 Foo 实例。
线程 A 将会调用 one() 方法
线程 B 将会调用 two() 方法
线程 C 将会调用 three() 方法
请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。
示例 1:
输入: [1,2,3]
输出: "onetwothree"
解释:
有三个线程会被异步启动。
输入 [1,2,3] 表示线程 A 将会调用 one() 方法,线程 B 将会调用 two() 方法,线程 C 将会调用 three() 方法。
正确的输出是 "onetwothree"。
示例 2:
输入: [1,3,2]
输出: "onetwothree"
解释:
输入 [1,3,2] 表示线程 A 将会调用 one() 方法,线程 B 将会调用 three() 方法,线程 C 将会调用 two() 方法。
正确的输出是 "onetwothree"。
注意:
尽管输入中的数字似乎暗示了顺序,但是我们并不保证线程在操作系统中的调度顺序。
你看到的输入格式主要是为了确保测试的全面性。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/print-in-order
解题思路
- 1.定义一个flag信号量及对象锁lock
- 2.定义三个方法first,second,third用来分别执行A,B,C三个线程,并且在run()前增加限制,执行后更新flag值。比如:first执行条件为flag=0(即C线程执行完),A线程执行完后,flag设置为1表示可以执行B线程了
- 3.通过以上设置,保存了A,B,C线程按顺序执行,这里题目要求从A线程要第一个执行,所以要把flag信号量初始值为0
代码实现
public class Sub1114 {
public static void main(String[] args) throws InterruptedException {
//测试用例字符串
int[] runOrder = new int[]{2, 3, 1};
//生成结果字符串
StringBuffer result = new StringBuffer();
Runnable one = () -> result.append("one");
Runnable two = () -> result.append("two");
Runnable three = () -> result.append("three");
Foo foo = new Foo();
Thread threads[] = new Thread[runOrder.length];
for (int i = 0; i < runOrder.length; ++i) {
Thread thread = null;
if (runOrder[i] == 1) {
thread = new FirstThread(foo, one);
} else if (runOrder[i] == 2) {
thread = new SecondThread(foo, two);
} else if (runOrder[i] == 3) {
thread = new ThirdThread(foo, three);
}
thread.start();
threads[i] = thread;
}
//等侍所有线程执行完
for (int i = 0; i < threads.length; i++) {
threads[i].join();
}
//输出结果串
System.out.println(result.toString());
}
}
class FirstThread extends Thread {
Foo foo;
Runnable runnable;
public FirstThread(Foo h2o, Runnable runnable) {
this.foo = h2o;
this.runnable = runnable;
}
@Override
public void run() {
try {
foo.first(runnable);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class SecondThread extends Thread {
Foo foo;
Runnable runnable;
public SecondThread(Foo h2o, Runnable runnable) {
this.foo = h2o;
this.runnable = runnable;
}
@Override
public void run() {
try {
foo.second(runnable);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThirdThread extends Thread {
Foo foo;
Runnable runnable;
public ThirdThread(Foo h2o, Runnable runnable) {
this.foo = h2o;
this.runnable = runnable;
}
@Override
public void run() {
try {
foo.third(runnable);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Foo {
//信号量
private int flag = 0;
//定义Object对象为锁
private Object lock = new Object();
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
synchronized (lock) {
//如果flag不为0则让first线程等待,while循环控制first线程如果不满住条件就一直在while代码块中,防止出现中途跳入,执行下面的代码,其余线程while循环同理
while (flag != 0) {
lock.wait();
}
printFirst.run();
//定义成员变量为 1
flag = 1;
//唤醒其余所有的线程
lock.notifyAll();
}
}
public void second(Runnable printSecond) throws InterruptedException {
synchronized (lock) {
//如果成员变量不为1则让二号等待
while (flag != 1) {
lock.wait();
}
printSecond.run();
//如果成员变量为 1 ,则代表first线程刚执行完,所以执行second,并且改变成员变量为 2
flag = 2;
//唤醒其余所有的线程
lock.notifyAll();
}
}
public void third(Runnable printThird) throws InterruptedException {
synchronized (lock) {
//如果flag不等于2 则一直处于等待的状态
while (flag != 2) {
lock.wait();
}
//如果成员变量为 2 ,则代表second线程刚执行完,所以执行third,并且改变成员变量为 0
printThird.run();
flag = 0;
lock.notifyAll();
}
}
}
资料
LeetCode 按序打印的更多相关文章
- LeetCode:按序打印【1114】
LeetCode:按序打印[1114] 题目描述 我们提供了一个类: 1 2 3 4 5 public class Foo { public void one() { print("on ...
- ERP按序打印问题
按序打印只适合一个机器,不适合主副机模式,主副机模式请勾选同时打印 如果开启主副机模式勾选了按序打印,会造成副机下厨后厨不出单
- LeetCode:打印零与奇偶数【1116】
LeetCode:打印零与奇偶数[1116] 题目描述 假设有这么一个类: class ZeroEvenOdd { public ZeroEvenOdd(int n) { ... } // 构造函数 ...
- Java多线程wait和notify协作,按序打印abc
有一个经典的多线程面试题:启三个线程,按序打印ABC 上代码: package cn.javaBase.study_thread1; class MyRunnable1 implements Runn ...
- LeetCode 从头到尾打印链表
LeetCode 从头到尾打印链表 题目描述 输入一个链表头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入:head = [1,3,2] 输出:[2,3,1] 一得之见(Jav ...
- (LeetCode)1114. 按序打印
题目来源:https://leetcode-cn.com/problems/print-in-order/ 我们提供了一个类: public class Foo { public void one( ...
- [LeetCode]1114. 按序打印(并发)
####题目 我们提供了一个类: public class Foo { public void one() { print("one"); } public void tw ...
- LeetCode:交替打印【1115】
LeetCode:交替打印[1115] 题目描述 我们提供一个类: class FooBar { public void foo() { for (int i = 0; i < n; i++) ...
- LeetCode 题解目录
前言 本目录将不断更新记录leetcode的刷题日记. 二叉树 序号 标题 难度 标签 1 108 将有序数组转换为二叉搜索树 简单 树.深度优先搜索 2 538 把二叉搜索树转换为累加树 简单 树 ...
随机推荐
- 这货到底还是不是垃圾?【垃圾回收GC算法JVM篇四】
目录 1.判断对象是否存活的JVM两种计数算法 2.垃圾收集算法 3.垃圾回收算法小结 垃圾收集 Garbage Collection 通常被称为"GC", 在jvm 中,程序计数 ...
- Web安全-之文件上传漏洞场景
1 上传漏洞危害介绍 上传是Web中最常见的功能,如果上传功能存在设计.编码缺陷,就容易形成上传漏洞,从而成为致命的安全问题,攻击者可以通过上传脚本木马,实现查看/篡改/删除源码和任意涂鸦网页,可 ...
- Redis自动化安装以及集群实现
Redis实例安装 安装说明:自动解压缩安装包,按照指定路径编译安装,复制配置文件模板到Redis实例路的数据径下,根据端口号修改配置文件模板 三个必须文件:1,配置文件,2,当前shell脚本,3, ...
- MySQL的存储(二、创建表并插入)
创建表 首先创建一个 spiders的数据库 cursor.execute("create database spiders default character set utf8" ...
- set容器
set容器简介: 1) set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. 2) set采用红黑树变体的数据结构实现,红 ...
- iOS10 openURL方法跳转到设置界面
问题 在iOS10之前,跳转到系统设置界面的某个指定界面的方式如下: //打开定位服务界面 NSURL*url=[NSURL URLWithString:@"prefs:root=Priva ...
- GRPC的metadata使用
文章目录 一.简析 1.创建metadata 2.发送metadata 3.接收metadata 二.代码举例 1.proto文件编写 2.server端编写 3.client端编写 三.实际使用举例 ...
- go实践之apiserver搭建
文章目录 go实践之apiserver搭建 1.配置文件读取 2.数据连接 3.日志初始化 4.server初始化 5.接口编写 go实践之apiserver搭建 本文主要记录下博主用gin搭建app ...
- Zabbix与ELK整合实现对日志数据的实时监控
4.2.zabbix平台配置日志告警 一. ELK与zabbix有什么关系? ELK大家应该比较熟悉了,zabbix应该也不陌生,那么将ELK和zabbix放到一起的话,可能大家就有疑问了?这两个放到 ...
- Docker学习-环境搭建
ChuanGoing 2019-12-15 本篇是DevOps Docker介绍第一篇,首先说下为何另开一篇来讲解本系列. 原因有二: 1.重新复习下个人对于DevOps/Docker的学习之路 2. ...