第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 按序打印的更多相关文章

  1. LeetCode:按序打印【1114】

    LeetCode:按序打印[1114] 题目描述 我们提供了一个类: 1 2 3 4 5 public class Foo {   public void one() { print("on ...

  2. ERP按序打印问题

    按序打印只适合一个机器,不适合主副机模式,主副机模式请勾选同时打印 如果开启主副机模式勾选了按序打印,会造成副机下厨后厨不出单

  3. LeetCode:打印零与奇偶数【1116】

    LeetCode:打印零与奇偶数[1116] 题目描述 假设有这么一个类: class ZeroEvenOdd { public ZeroEvenOdd(int n) { ... } // 构造函数 ...

  4. Java多线程wait和notify协作,按序打印abc

    有一个经典的多线程面试题:启三个线程,按序打印ABC 上代码: package cn.javaBase.study_thread1; class MyRunnable1 implements Runn ...

  5. LeetCode 从头到尾打印链表

    LeetCode 从头到尾打印链表 题目描述 输入一个链表头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入:head = [1,3,2] 输出:[2,3,1] 一得之见(Jav ...

  6. (LeetCode)1114. 按序打印

    题目来源:https://leetcode-cn.com/problems/print-in-order/ 我们提供了一个类: public class Foo {  public void one( ...

  7. [LeetCode]1114. 按序打印(并发)

    ####题目 我们提供了一个类: public class Foo {   public void one() { print("one"); }   public void tw ...

  8. LeetCode:交替打印【1115】

    LeetCode:交替打印[1115] 题目描述 我们提供一个类: class FooBar { public void foo() { for (int i = 0; i < n; i++) ...

  9. LeetCode 题解目录

    前言 本目录将不断更新记录leetcode的刷题日记. 二叉树 序号 标题 难度 标签 1 108 将有序数组转换为二叉搜索树 简单 树.深度优先搜索 2 538 把二叉搜索树转换为累加树 简单 树 ...

随机推荐

  1. 这货到底还是不是垃圾?【垃圾回收GC算法JVM篇四】

    目录 1.判断对象是否存活的JVM两种计数算法 2.垃圾收集算法 3.垃圾回收算法小结 垃圾收集 Garbage Collection 通常被称为"GC", 在jvm 中,程序计数 ...

  2. Web安全-之文件上传漏洞场景

    1   上传漏洞危害介绍 上传是Web中最常见的功能,如果上传功能存在设计.编码缺陷,就容易形成上传漏洞,从而成为致命的安全问题,攻击者可以通过上传脚本木马,实现查看/篡改/删除源码和任意涂鸦网页,可 ...

  3. Redis自动化安装以及集群实现

    Redis实例安装 安装说明:自动解压缩安装包,按照指定路径编译安装,复制配置文件模板到Redis实例路的数据径下,根据端口号修改配置文件模板 三个必须文件:1,配置文件,2,当前shell脚本,3, ...

  4. MySQL的存储(二、创建表并插入)

    创建表 首先创建一个 spiders的数据库 cursor.execute("create database spiders default character set utf8" ...

  5. set容器

    set容器简介: 1) set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. 2) set采用红黑树变体的数据结构实现,红 ...

  6. iOS10 openURL方法跳转到设置界面

    问题 在iOS10之前,跳转到系统设置界面的某个指定界面的方式如下: //打开定位服务界面 NSURL*url=[NSURL URLWithString:@"prefs:root=Priva ...

  7. GRPC的metadata使用

    文章目录 一.简析 1.创建metadata 2.发送metadata 3.接收metadata 二.代码举例 1.proto文件编写 2.server端编写 3.client端编写 三.实际使用举例 ...

  8. go实践之apiserver搭建

    文章目录 go实践之apiserver搭建 1.配置文件读取 2.数据连接 3.日志初始化 4.server初始化 5.接口编写 go实践之apiserver搭建 本文主要记录下博主用gin搭建app ...

  9. Zabbix与ELK整合实现对日志数据的实时监控

    4.2.zabbix平台配置日志告警 一. ELK与zabbix有什么关系? ELK大家应该比较熟悉了,zabbix应该也不陌生,那么将ELK和zabbix放到一起的话,可能大家就有疑问了?这两个放到 ...

  10. Docker学习-环境搭建

    ChuanGoing 2019-12-15 本篇是DevOps Docker介绍第一篇,首先说下为何另开一篇来讲解本系列. 原因有二: 1.重新复习下个人对于DevOps/Docker的学习之路 2. ...