惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Blog of Author Tim Ferriss
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
云风的 BLOG
云风的 BLOG
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
P
Palo Alto Networks Blog
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
S
Schneier on Security
Engineering at Meta
Engineering at Meta
I
InfoQ
L
LangChain Blog
Cyberwarzone
Cyberwarzone
T
Tenable Blog
WordPress大学
WordPress大学
P
Privacy & Cybersecurity Law Blog
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Jina AI
Jina AI
C
CERT Recently Published Vulnerability Notes
Scott Helme
Scott Helme
博客园 - 三生石上(FineUI控件)
酷 壳 – CoolShell
酷 壳 – CoolShell
Know Your Adversary
Know Your Adversary
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Last Watchdog
The Last Watchdog
Last Week in AI
Last Week in AI
Cloudbric
Cloudbric
S
SegmentFault 最新的问题
爱范儿
爱范儿
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 叶小钗
AI
AI
T
Tor Project blog
I
Intezer
T
Threatpost
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
Visual Studio Blog
N
News and Events Feed by Topic
Latest news
Latest news
S
Security Affairs
博客园 - Franky
Microsoft Security Blog
Microsoft Security Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
B
Blog RSS Feed
C
Cybersecurity and Infrastructure Security Agency CISA
Hugging Face - Blog
Hugging Face - Blog
小众软件
小众软件
S
Securelist

博客园 - Nucky_yang

windows系统下安装openclaw,无权限打开软件,无权限打开浏览器,无权限读写文件的问题。 just a demo presto集成 hive(转载) java可重入锁与不可重入锁 的设计 动态规划 背包问题 java ThreadPoolExecutor线程池在美团的最佳实践 回溯 八皇后问题 与 0-1背包 技术学习 计算机网络基础知识总结(各种协议) 大数据Phoenix专题 ClickHouse深度揭秘 hbase 查询组件phoenix redis的设计与实现 第二版 位图 Java并发编程:volatile关键字解析 socket 多路复用原理和代码 select poll epoll mongDB需要注意的事项和 监控命令mongostat mongotop mongoDB的事务 mongoDB学习 mongo的聚合框架、join
线程间通信
Nucky_yang · 2020-10-14 · via 博客园 - Nucky_yang

传送门

https://blog.nowcoder.net/n/29dfac7b41b54be180aa4c2eb68dacb6

问题描述

有4个线程和1个公共的字符数组。线程1的功能就是向数组输出A,线程2的功能就是向字符输出B,线程3的功能就是向数组输出C,线程4的功能就是向数组输出D。要求按顺序向数组赋值ABCDABCDABCD,ABCD的个数由线程函数1的参数指定。

示例1

输入
10

输出
ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD

解题思路

线程交替打印

线程交替打印需要用到线程通信的知识。其他的方法我不太了解,首先想到的就是用Condition来实现线程之间的通信。刚开始写好代码,本地运行,多组测试结果什么的都正确,但是一到线上运行,打印的结果就是乱的,之前从来没有遇到过这种情况,想了我一个多小时。最后突然想到测试用例输入的时候和在本地运行输入的情况有点不一样。因为需要多组测试,所以需要定义一个while(scanner.hasNext()){...}的循环体。本地测试由于是我们手动输入的,在下一次输入之前,前一次的打印结果就已经全部结束了(四个线程已经运行结束)。但是线上是机器测试的,可能前一次的测试还没打印结束,下一次的测试又开始了,所以会导致两次的测试数据会穿插在一起。
知道了原因,就好办了,只要做到每一次测试打印结束后while(){}循环才能结束,首先想到的就是用CountdownLatch。每次while循环开始就定义一个countdownLatch(4),每个线程结束后计数器就减一,减到0后再进行下一组数据的测试。
代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

import java.util.Scanner;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

/**

 * 多线程,线程交替打印ABCDABCD

 */

public class Test49 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNext()) {

            int n = scanner.nextInt();

            CountDownLatch countDownLatch = new CountDownLatch(4);

            AlternativePrint alternativePrint = new AlternativePrint();

            new Thread(new Runnable() {

                @Override

                public void run() {

                    try {

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

                            alternativePrint.printA();

                        }

                    finally {

                        countDownLatch.countDown();

                    }

                }

            }).start();

            new Thread(new Runnable() {

                @Override

                public void run() {

                    try {

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

                            alternativePrint.printB();

                        }

                    finally {

                        countDownLatch.countDown();

                    }

                }

            }).start();

            new Thread(new Runnable() {

                @Override

                public void run() {

                    try {

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

                            alternativePrint.printC();

                        }

                    finally {

                        countDownLatch.countDown();

                    }

                }

            }).start();

            new Thread(new Runnable() {

                @Override

                public void run() {

                    try {

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

                            alternativePrint.printD();

                        }

                    finally {

                        countDownLatch.countDown();

                    }

                }

            }).start();

            try {

                countDownLatch.await();

            catch (InterruptedException e) {

                e.printStackTrace();

            }

            System.out.println();

        }

    }

}

class AlternativePrint {

    private Lock lock = new ReentrantLock();

    private Condition conditionA = lock.newCondition();

    private Condition conditionB = lock.newCondition();

    private Condition conditionC = lock.newCondition();

    private Condition conditionD = lock.newCondition();

    private int number = 1;

    void printA() {

        lock.lock();

        try {

            if (number != 1) {

                conditionA.await();

            }

            System.out.print("A");

            number = 2;

            conditionB.signal();

        catch (InterruptedException e) {

            e.printStackTrace();

        finally {

            lock.unlock();

        }

    }

    void printB() {

        lock.lock();

        try {

            if (number != 2) {

                conditionB.await();

            }

            System.out.print("B");

            number = 3;

            conditionC.signal();

        catch (InterruptedException e) {

            e.printStackTrace();

        finally {

            lock.unlock();

        }

    }

    void printC() {

        lock.lock();

        try {

            if (number != 3) {

                conditionC.await();

            }

            System.out.print("C");

            number = 4;

            conditionD.signal();

        catch (InterruptedException e) {

            e.printStackTrace();

        finally {

            lock.unlock();

        }

    }

    void printD() {

        lock.lock();

        try {

            if (number != 4) {

                conditionD.await();

            }

            System.out.print("D");

            number = 1;

            conditionA.signal();

        catch (InterruptedException e) {

            e.printStackTrace();

        finally {

            lock.unlock();

        }

    }

}