多线程计数器
1. 主要功能
- 请用“等待唤醒”机制编写一个程序,要求:
- 第一个线程:遍历 1–1000 所有的数字,在遍历过程中,如果发现这个数字能同时被 2,3,5,7 整除,立即 wait() 退出等待,让第二个线程进入;
- 第二个线程:运行后,将一个计数器 + 1,之后再唤醒等待的线程;
- 主线程中:休息 2 秒,让两个线程全部执行完毕,打印“计数器”的结果;
- 注意:第二个线程使用的计数器,要定义在线程外部;
2. Java 实现
public class Test {
//开关,isCount用于标记统不统计:true就表示要统计,false表示不统计
static volatile boolean isCount = false;
static volatile boolean isFinished = false;
//用于统计能被整除的数字的个数
static volatile int counter = 0;
public static void main(String[] args) {
/*
请用“等待唤醒”机制编写一个程序,要求:
第一个线程:遍历1--1000所有的数字,在遍历过程中,如果发现这个数字能同时被
2,3,5,7整除,立即wait()退出等待,让第二个线程进入。
第二个线程:运行后,将一个计数器 + 1,之后再唤醒等待的线程。
主线程中:休息2秒,让两个线程全部执行完毕,打印“计数器”的结果。
注意:第二个线程使用的计数器,要定义在线程外部。
*/
//生产消费设计模式: 开关控制生产和消费交错运行,关键在于定义这个开关
// 开关切换的机制:遍历的数字能否被2,3,5,7同时整除
Runnable r1 = () -> {
for (int i = 1; i < 1001; i++) {
//能别几个数同时整除,就被被这几个数的最小公倍数整数,2*3*5*7
synchronized ("") {
if (i % (2 * 3 * 5 * 7) == 0) {
isCount = true;
//发现需要统计,等待统计线程计算
try {
System.out.println("遍历线程发现整除数i:" + i + ",counter:" + counter + ",icCount:" + isCount);
//唤醒统计线程
"".notify();
//进入等待状态
"".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
synchronized ("") {
//遍历完毕
isFinished = true;
System.out.println("遍历完毕,isFinished:" + isFinished);
"".notify();//这里还notify的原因是怕统计线程还在wait()
}
};
//int count = 0;//局部变量在匿名内部类中会被当成final修饰
Runnable r2 = () -> {
//只要还没遍历结束
while (!isFinished) {
synchronized ("") {
if (isCount == true) {
//统计过程:统计完毕之后,更改开关,进入wait状态
counter++;
isCount = false;
try {
System.out.println("统计线程统计,counter:" + counter + ",icCount:" + isCount);
//唤醒等待线程
"".notify();
//进入等待状态
"".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
System.out.println("统计线程结束,isFinished:" + isFinished);
};
new Thread(r1).start();
new Thread(r2).start();
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter);
}
}