Java 多线程-经典编程题
- 手写死锁
- 手写生产者消费者模型
- 三个线程顺序打印 ABC
- 三个线程循环顺序打印 ABC 十次
手写死锁
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
public class DeadLockDemo {
private static final Object resource1 = new Object(); // 资源1
private static final Object resource2 = new Object(); // 资源2
public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread().getName() + " 获取资源1");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 等待资源2");
synchronized (resource2) {
System.out.println(Thread.currentThread().getName() + " 获取资源2");
}
}
}, "线程1").start();
new Thread(() -> {
synchronized (resource2) {
System.out.println(Thread.currentThread().getName() + " 获取资源2");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 等待资源1");
synchronized (resource1) {
System.out.println(Thread.currentThread().getName() + " 获取资源1");
}
}
}, "线程2").start();
}
}
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
public class DeadLockDemo {
public static void main(String[] args) {
new DeadLockDemo().deadLock();
}
private final String A = "A";
private final String B = "b";
public void deadLock() {
Thread t1 = new Thread(() -> {
synchronized (A) {
System.out.println(Thread.currentThread().getName() + " 线程获得了锁 A,尝试获取锁 B。");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B) {
}
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (B) {
System.out.println(Thread.currentThread().getName() + " 线程获得了锁 B,尝试获取锁 A。");
synchronized (A) {
}
}
}, "t2");
t1.start();
t2.start();
}
}
手写生产者消费者模型
1. 使用 synchronized 和 wait/notify/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
public class ProducerConsumerExample {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
int maxSize = 5;
Thread producer = new Thread(new Producer(queue, maxSize), "Producer");
Thread consumer = new Thread(new Consumer(queue), "Consumer");
producer.start();
consumer.start();
}
}
class Producer implements Runnable {
private final Queue<Integer> queue;
private final int maxSize;
public Producer(Queue<Integer> queue, int maxSize) {
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
int value = 0;
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Producing value: " + value);
queue.add(value++);
queue.notifyAll();
}
}
}
}
class Consumer implements Runnable {
private final Queue<Integer> queue;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consuming value: " + queue.remove());
queue.notifyAll();
}
}
}
}
2. 使用 BlockingQueue 实现
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 ProducerConsumerExample {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(5);
Thread producer = new Thread(new Producer(queue), "Producer");
Thread consumer = new Thread(new Consumer(queue), "Consumer");
producer.start();
consumer.start();
}
}
class Producer implements Runnable {
private final BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
int value = 0;
while (true) {
try {
System.out.println("Producing value: " + value);
queue.put(value++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
private final BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
try {
System.out.println("Consuming value: " + queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
三个线程顺序打印 ABC
1. 使用 join() 实现
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
public class OrderedPrintABC {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A");
});
Thread t2 = new Thread(() -> {
try {
t1.join();
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B");
});
Thread t3 = new Thread(() -> {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("C");
});
t1.start();
t2.start();
t3.start();
}
}
2. 使用线程池的 ExecutorService 顺序执行
1
2
3
4
5
6
7
8
9
public class OrderedPrintABC {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> System.out.println("A"));
executor.execute(() -> System.out.println("B"));
executor.execute(() -> System.out.println("C"));
executor.shutdown();
}
}
3. 使用 CountDownLatch 实现
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
public class OrderedPrintABC {
public static void main(String[] args) {
CountDownLatch latch1 = new CountDownLatch(1);
CountDownLatch latch2 = new CountDownLatch(1);
Thread t1 = new Thread(() -> {
System.out.println("A");
latch1.countDown();
});
Thread t2 = new Thread(() -> {
try {
latch1.await();
System.out.println("B");
latch2.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t3 = new Thread(() -> {
try {
latch2.await();
System.out.println("C");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
t3.start();
}
}
4. 使用 synchronized 和 wait/notify/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
public class OrderedPrintABC {
private static final Object lock = new Object();
private static int state = 0;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (lock) {
while (state % 3 != 0) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
state++;
lock.notifyAll();
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
while (state % 3 != 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
state++;
lock.notifyAll();
}
});
Thread t3 = new Thread(() -> {
synchronized (lock) {
while (state % 3 != 2) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
state++;
lock.notifyAll();
}
});
t1.start();
t2.start();
t3.start();
}
}
5. 使用 ReentrantLock 和 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
public class OrderedPrintABC {
private static final ReentrantLock lock = new ReentrantLock();
private static final Condition condition = lock.newCondition();
private static int state = 0;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
lock.lock();
try {
while (state % 3 != 0) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
state++;
condition.signalAll();
} finally {
lock.unlock();
}
});
Thread t2 = new Thread(() -> {
lock.lock();
try {
while (state % 3 != 1) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
state++;
condition.signalAll();
} finally {
lock.unlock();
}
});
Thread t3 = new Thread(() -> {
lock.lock();
try {
while (state % 3 != 2) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
state++;
condition.signalAll();
} finally {
lock.unlock();
}
});
t1.start();
t2.start();
t3.start();
}
}
三个线程循环顺序打印 ABC 十次
1. 使用 synchronized 和 wait/notify/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
public class PrintABC {
private static final int PRINT_COUNT = 10;
private static final int THREAD_COUNT = 3;
private static volatile int currentCount = 0;
public static void main(String[] args) {
Object lock = new Object();
for (int i = 0; i < THREAD_COUNT; i++) {
new Thread(new PrintTask(lock, i), String.valueOf((char) ('A' + i))).start();
}
}
private static class PrintTask implements Runnable {
private final Object lock;
private final int targetNum;
public PrintTask(Object lock, int targetNum) {
this.lock = lock;
this.targetNum = targetNum;
}
@Override
public void run() {
for (int i = 0; i < PRINT_COUNT; i++) {
synchronized (lock) {
while (currentCount % THREAD_COUNT != targetNum) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(Thread.currentThread().getName());
currentCount++;
lock.notifyAll();
}
}
}
}
}
2. 使用 ReentrantLock 和 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
public class PrintABC {
private static int threadCount;
private static int printCount;
private static int currentCount = 0;
private static final Lock lock = new ReentrantLock();
private static Condition[] conditions;
public static void main(String[] args) {
threadCount = 3;
printCount = 10;
conditions = new Condition[threadCount];
for (int i = 0; i < threadCount; i++) {
conditions[i] = lock.newCondition();
}
for (int i = 0; i < threadCount; i++) {
new Thread(new PrintTask(i), String.valueOf((char) ('A' + i))).start();
}
}
static class PrintTask implements Runnable {
private final int threadIndex;
public PrintTask(int threadIndex) {
this.threadIndex = threadIndex;
}
@Override
public void run() {
while (true) {
lock.lock();
try {
if (currentCount >= threadCount * printCount) {
break;
}
while (currentCount % threadCount != threadIndex) {
conditions[threadIndex].await();
}
System.out.print(Thread.currentThread().getName());
currentCount++;
conditions[(threadIndex + 1) % threadCount].signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
}
CC BY-NC-SA 4.0
许可协议,转载请注明出处!
本博客所有文章除特别声明外,均采用