面试题:抛砖引玉
方式1:
package com.shuchang;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 本题目主要考察线程间通信问题:
* 题目描述:使用三个线程,一个线程打印 X,一个线程打印 Y,一个线程打印 Z,按顺序打印X,Y,Z,连续打印10次XYZ。
*
* @Author wsc
* 2021-09-13 21:23
**/
public class PrintXYZ1 {
//定义一把lock锁对象
static Lock lock = new ReentrantLock();
//使用lock锁获取三个Condition条件
static Condition con1 = lock.newCondition();
static Condition con2 = lock.newCondition();
static Condition con3 = lock.newCondition();
// 线程执行标记
static int flag = 1;
public static void printX() throws InterruptedException {
lock.lock();
while (flag != 1) {
con1.await();
}
flag = 2;
System.out.print("X");
con2.signal();
lock.unlock();
}
public static void printY() throws InterruptedException {
lock.lock();
while (flag != 2) {
con2.await();
}
flag = 3;
System.out.print("Y");
con3.signal();
lock.unlock();
}
public static void printZ() throws InterruptedException {
lock.lock();
while (flag != 3) {
con3.await();
}
flag = 1;
System.out.println("Z");
con1.signal();
lock.unlock();
}
public static void main(String[] args) {
//X线程
Thread x = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
printX();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//Y线程
Thread y = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
printY();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//Z线程
Thread z = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
printZ();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
x.start();
y.start();
z.start();
}
}
方式2:
package com.shuchang;
import java.util.concurrent.CountDownLatch;
/**
* 本题目主要考察线程间通信问题:
* 题目描述:使用三个线程,一个线程打印 X,一个线程打印 Y,一个线程打印 Z,按顺序打印X,Y,Z,连续打印10次XYZ。
* @Author wsc
* 2021-09-13 21:23
**/
public class PrintXYZ2 {
//定义CountDownLatch,起到线程通知的作用
private static CountDownLatch cdl1 = new CountDownLatch(1);
private static CountDownLatch cdl2 = new CountDownLatch(1);
private static CountDownLatch cdl3 = new CountDownLatch(1);
public static void main(String[] args) {
Thread x = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
//线程启动之后等待,直到con1的门闩变为0
cdl1.await();
System.out.print("X");
//将cdl2的门闩减为0,使cdl2可以从等待返回
cdl2.countDown();
//新建一个CountDownLatch用于下一次循环
cdl1 = new CountDownLatch(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"printX");
Thread y = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
cdl2.await();
System.out.print("Y");
cdl3.countDown();
cdl2 = new CountDownLatch(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"printY");
Thread z = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
cdl3.await();
System.out.println("Z");
cdl1.countDown();
cdl3 = new CountDownLatch(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"printZ");
x.start();
y.start();
z.start();
//三个线程启动完都会等待各自的门闩
//cdl1门闩先减为0,意味着线程printX会先从等待中返回,从而先打印X
cdl1.countDown();
}
}
打印结果:
D:\Tools\jdk1.8.0_231\bin\java.exe ...
XYZ
XYZ
XYZ
XYZ
XYZ
XYZ
XYZ
XYZ
XYZ
XYZ
Process finished with exit code 0