0%

面试中可能出的多线程手撕题目

多个线程交叉打印,多种方法

多线程交叉打印ABC

wait、notifyAll实现

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
public class PrintABCWithWaitNotify {
private final Object lock = new Object();
private int state = 0; // A:0 B:1 C:2

public static void main(String[] args) {
PrintABCWithWaitNotify task = new PrintABCWithWaitNotify();
Thread threadA = new Thread(task::printA);
Thread threadB = new Thread(task::printB);
Thread threadC = new Thread(task::printC);

threadA.start();
threadB.start();
threadC.start();
}

public void printA() {
synchronized (lock) {
for(int i = 0; i < 10; i ++ ) {
while(state != 0) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print("A");
state = 1;
lock.notifyAll();
}
}
}

public void printB() {
synchronized (lock) {
for(int i = 0; i < 10; i ++ ) {
while(state != 1) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print("B");
state = 2;
lock.notifyAll();
}
}
}

public void printC() {
synchronized (lock) {
for(int i = 0; i < 10; i ++ ) {
while(state != 2) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("C");
state = 0;
lock.notifyAll();
}
}
}

}

lock和condition实现

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
public class PrintABCWithReentrantLock {
private final Lock lock = new ReentrantLock();
// 条件变量代替wait notifyAll
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition();
private int state = 0;

public static void main(String[] args) {
PrintABCWithReentrantLock task = new PrintABCWithReentrantLock();
Thread threadA = new Thread(task::printA);
Thread threadB = new Thread(task::printB);
Thread threadC = new Thread(task::printC);

threadA.start();
threadB.start();
threadC.start();
}

public void printA() {
lock.lock();
try {
for(int i = 0; i < 10; i ++ ) {
while(state != 0) {
try {
conditionA.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print("A");
state = 1;
conditionB.signal();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}

public void printB() {
lock.lock(); // 获取锁
try {
for(int i = 0; i < 10; i ++ ) {
while(state != 1) {
try {
conditionB.await(); // 不满足条件时等待
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print("B");
state = 2;
conditionC.signal();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}

public void printC() {
lock.lock();
try {
for(int i = 0; i < 10; i ++ ) {
while(state != 2) {
try {
conditionC.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("C");
state = 0;
conditionA.signal();
}
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}

信号量实现

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
public class PrintABCWithSemaphore {
private final Semaphore semA = new Semaphore(1);
private final Semaphore semB = new Semaphore(0);
private final Semaphore semC = new Semaphore(0);

public static void main(String[] args) {
PrintABCWithSemaphore task = new PrintABCWithSemaphore();
Thread threadA = new Thread(task::printA);
Thread threadB = new Thread(task::printB);
Thread threadC = new Thread(task::printC);

threadA.start();
threadB.start();
threadC.start();
}

public void printA() {
try{
for(int i = 0; i < 10; i ++ ) {
semA.acquire();
System.out.print("A");
semB.release();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

public void printB() {
try{
for(int i = 0; i < 10; i ++ ) {
semB.acquire();
System.out.print("B");
semC.release();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

public void printC() {
try{
for(int i = 0; i < 10; i ++ ) {
semC.acquire();
System.out.println("C");
semA.release();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

循环栅栏实现

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
public class PrintABCWithCyclicBarrier {
// 表示需要三个线程到达屏障点再继续下一轮执行
private final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
private int state = 0;
public static void main(String[] args) {
PrintABCWithCyclicBarrier task = new PrintABCWithCyclicBarrier();
Thread threadA = new Thread(task::printA);
Thread threadB = new Thread(task::printB);
Thread threadC = new Thread(task::printC);

threadA.start();
threadB.start();
threadC.start();
}

public void printA() {
try {
for(int i = 0; i < 10; i ++ ) {
cyclicBarrier.await();
while(state != 0) {

}
System.out.print("A");
state = 1;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
}

public void printB() {
try {
for(int i = 0; i < 10; i ++ ) {
cyclicBarrier.await();
while(state != 1) {

}
System.out.print("B");
state = 2;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
}

public void printC() {
try {
for(int i = 0; i < 10; i ++ ) {
cyclicBarrier.await();
while(state != 2) {

}
System.out.println("C");
state = 0;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
}
}

多线程交叉打印奇数、偶数

wait、notifyAll实现

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
public class PrintOddEvenWithWaitNotify {
private final Object lock = new Object();
private int state = 1;

public static void main(String[] args) {
PrintOddEvenWithWaitNotify task = new PrintOddEvenWithWaitNotify();
Thread printOdd = new Thread(task::printOdd);
Thread printEven = new Thread(task::printEven);
printOdd.start();
printEven.start();
}

public void printOdd() {
synchronized (lock) {
while(state <= 20) {
if(state % 2 == 0) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else {
System.out.println(state);
state ++;
lock.notifyAll();
}
}
}
}

public void printEven() {
synchronized (lock) {
while(state <= 20) {
if(state % 2 == 1) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else {
System.out.println(state);
state ++;
lock.notifyAll();
}
}
}
}
}

lock和condition实现

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
public class PrintOddEvenWithReentrantLock {
private final Lock lock = new ReentrantLock();
private final Condition conditionOdd = lock.newCondition();
private final Condition conditionEven = lock.newCondition();
private int count = 1;

public static void main(String[] args) {
PrintOddEvenWithReentrantLock task = new PrintOddEvenWithReentrantLock();
Thread printOdd = new Thread(task::pirntOdd);
Thread printEven = new Thread(task::pirntEven);

printOdd.start();
printEven.start();
}

public void pirntOdd() {
lock.lock();
try {
while(count <= 100) {
if(count % 2 == 0) {
conditionOdd.await();
}else {
System.out.println(count);
count ++;
conditionEven.signal();
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}

public void pirntEven() {
lock.lock();
try {
while(count <= 100) {
if(count % 2 == 1) {
conditionEven.await();
}else {
System.out.println(count);
count ++;
conditionOdd.signal();
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}

信号量实现

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
public class PrintOddEvenWithSemaphore {
private final Semaphore semOdd = new Semaphore(1);
private final Semaphore semEven = new Semaphore(0);
private int count = 1;

public static void main(String[] args) {
PrintOddEvenWithSemaphore task = new PrintOddEvenWithSemaphore();
Thread printOdd = new Thread(task::pirntOdd);
Thread printEven = new Thread(task::pirntEven);

printOdd.start();
printEven.start();
}

public void pirntOdd() {
while(count <= 100) {
try {
if(count % 2 == 0) {
semOdd.acquire();
}else {
System.out.println(count);
count ++;
semEven.release();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

public void pirntEven() {
while(count <= 100) {
try {
if(count % 2 == 1) {
semEven.acquire();
}else {
System.out.println(count);
count ++;
semOdd.release();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}

两个线程交叉打印数字和字母

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
public class PrintNumberAndLetter {
private final Semaphore semNum = new Semaphore(1);
private final Semaphore semLetter = new Semaphore(0);
int count = 1;
public static void main(String[] args) {
PrintNumberAndLetter task = new PrintNumberAndLetter();
Thread printNum = new Thread(task::printNum);
Thread printLetter = new Thread(task::printLetter);

printNum.start();
printLetter.start();
}

public void printNum() {
try {
while(count < 26) {
semNum.acquire();
System.out.print(count);
semLetter.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public void printLetter() {
try{
while(count <= 26) {
semLetter.acquire();
System.out.print((char)('A' + count - 1));
count ++;
semNum.release();
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}

使用N个线程打印1-100

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
public class PrintOddEvenWithNThread {
private static final int ThreadCount = 5;
private static final Lock lock = new ReentrantLock();
private static final Condition[] conditions;
int count = 1;

static {
conditions = new Condition[ThreadCount];
for(int i = 0; i < ThreadCount; i ++ ) {
conditions[i] = lock.newCondition();
}
}

public static void main(String[] args) {
PrintOddEvenWithNThread task = new PrintOddEvenWithNThread();
for(int i = 0; i < ThreadCount; i ++ ) {
final int id = i;
new Thread(() -> task.print(id)).start();
}
}

public void print(int threadId) {
while(count <= 100) {
lock.lock();
try {
while(count % ThreadCount != threadId) {
conditions[threadId].await();
}
if(count <= 100) {
System.out.println("ThreadId: " + threadId + " num:" + count);
}
count ++;
conditions[(threadId + 1) % ThreadCount].signal();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}
}

多线程交叉打印A5次,B10次,C15次,一共打印10轮

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
public class PrintA5B10C15 {
private final Lock lock = new ReentrantLock();
private final Condition conditionA = lock.newCondition();
private final Condition conditionB = lock.newCondition();
private final Condition conditionC = lock.newCondition();
private int state = 0;

public static void main(String[] args) {
PrintA5B10C15 task = new PrintA5B10C15();
new Thread(() -> task.print("A", 0, 5)).start();
new Thread(() -> task.print("B", 1, 10)).start();
new Thread(() -> task.print("C", 2, 15)).start();
}

public void print(String letter, int target, int times) {
for(int i = 0; i < 10; i ++ ) {
// 重复十次
try {
lock.lock(); // 获取锁
while(state != target) {
if(target == 0) {
conditionA.await();
}else if(target == 1) {
conditionB.await();
}else {
conditionC.await();
}
}
for(int j = 0; j < times; j ++ ) {
System.out.print(letter);
}
if(state == 2) {
System.out.println();
}
state = (state + 1) % 3;
if(target == 0) {
conditionB.signal();
}else if(target == 1) {
conditionC.signal();
}else {
conditionA.signal();
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}
}