面试被问到的题,回来看了下synchronized,wait(),notifyAll(),自己写了下代码,不知道是不是有问题,多次测试是可以实现,先做下记录,之后完善下,多写几种实现方式。
用到的技术
synchronized
这里就不多做介绍了,相信只要经历过面试这个这个肯定是熟悉的不能再熟悉了。
wait()函数
简单地说,当我们调用wait()方法时,会强制当前线程等待,直到某个其他线程在同一个对象上调用notify()或notifyAll();
notifyAll()函数
该方法只是唤醒正在此对象的监视器上等待的所有线程,可以唤醒之前调用wait()方法处于阻塞状态的线程;
实现思路
开启三个线程,给三个线程分别进行编号,可以在执行的时候进行编号的区分;在run方法执行时通过count对线程数量(3)进行取模来匹配是不是轮到该线程打印数字。
代码实现
/**
* 三个线程顺序打印递增数组1234567直到100
*
* @author xxx
* @date 2021/4/25
*/
public class Synchronized123 {
//打印的数字,从1开始,每次打印之后进行++操作
private static int count = 1;
//线程数量,这里题目要求3个线程
private static int threadCount = 3;
//对象锁
private static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
//这里用了下线程池,具体参数设置大家可以自行学习,相信经历过面试的同学都会相当清楚
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 20, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));
//执行三个线程,分别传入对应编号,第三个线程为0是为了取模结果为0
executor.execute(new MyThread(1));
executor.execute(new MyThread(2));
executor.execute(new MyThread(0));
}
static class MyThread extends Thread {
/**
* 很重要,用来记录当前线程编号
*/
private int threadNum;
public MyThread() {
}
public MyThread(int threadNum) {
this.threadNum = threadNum;
}
public void run() {
//run方法中真正执行的逻辑
//while循环,只要count小于等于100,就进去
while (count <= 100) {
//获取锁
synchronized (lock) {
//while循环count小于等于100,且count对线程数量取模==线程id,表示可以进入循环
while (count <= 100 && count % threadCount == this.threadNum) {
//打印数字,并进行++操作
System.out.println(Thread.currentThread().getName() + ":" + count++);
//进行完操作后唤醒其他线程
lock.notifyAll();
try {
//使得如下wait()方法的线程进入阻塞状态
if (count <= 100) {
//如果count不大于100.进入阻塞状态,等待被唤醒
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
}