java中多线程是并发编程的重要概念,它允许程序同时执行多个任务。通过多线程并行处理,系统能够更好的利用CPU和其他资源。但在有些情况下,需要保证多线程的顺序执行。通过wait、notity、notifyAll方法可以实现线程有序执行。
1、题目1:线程1 打印1,线程2打印2,线程3打印3。通过wait方法实现多线程顺序打印结果为123
1.分析
wait、notify、notifyAll是实现线程间通信和同步的,需谨慎的处理锁对象的获取和释放。可以通过共享的锁对象来控制线程的打印。每个线程在打印完成后,通知其他线程继续执行,由于顺序执行,还需一个表示当前应该打印哪个数字的标识(如 一个整数索引)。
2.逻辑
a.首选通过while循环检查index是否等于要打印的期望值number。
b.若不等,调用lock.wait方法使当前线程等待,直到其打印线程通过lock.notifyAll方法唤醒。
c.当index = number时,打印数字,并对index累加
d.使用lock.notifyAll方法唤醒所有在等待的线程
3.代码
代码实现多线程顺序打印
public class PrintOrder{
//共享锁对象
private final Object lock = new Object();
//实际打印数字的索引
private int index = 1;
public void print(int number){
synchronized(lock){
//等待当前索引与线程要打印的数字匹配
while(index != number){
try{
lock.wait();
}catch(InterruptedException e){
//重新设置中断状态
Thread.currentThread().interrupt();
return;
}
}
system.out.print(number);
//更新索引并通知其他线程
index++;
//确保所有等待的线程都被唤醒
lock.notifyAll();
}
}
public static void main(String[] args){
PrintOrder print = new PrintOrder();
Thread t1= new Thread(() -> print.print(1));
Thread t2= new Thread(() -> print.print(2));
Thread t3= new Thread(() -> print.print(3));
t1.start();
t2.start();
t3.start();
}
}
运行结果:123
4.代码解析
锁对象(lock):用来同步print方法中同步代码块,确保在任何时候只有一个线程可以访问这个代码块。
执行顺序:
a.首选通过while循环检查index是否等于要打印的期望值number。
b.若不等,调用lock.wait方法使当前线程等待,直到其打印线程通过lock.notifyAll方法唤醒。
c.当index = number时,打印数字,并对index累加
d.使用lock.notifyAll方法唤醒所有在等待的线程
线程执行(t1、t2、t3):每个线程都调用print方法,分别尝试打印1、2、3
2、题目2:在题目1的基础上,要求线程1、线程2、线程3无限循环打印出123123123....
题目2与题目1在问题分析和逻辑上基本保持一致,题目2在题目1的基础上需要解决线程无限循环的问题。
1、代码
public class PrintNumbers {
private int number = 1; // 控制打印的变量
private final Object lock = new Object(); // 锁对象
public void printNumber(int n) {
synchronized (lock) {
while (number != n) {
try {
lock.wait(); // 如果当前数字不是n,则等待
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 处理中断
}
}
// 打印数字
System.out.println(Thread.currentThread().getName() + ": " + number);
// 更新数字并通知其他线程
number = (number % 3) + 1; // 循环1, 2, 3
lock.notifyAll(); // 唤醒所有等待的线程
}
}
public static void main(String[] args) {
PrintNumbers pn = new PrintNumbers();
Thread t1 = new Thread(() -> {
while (true) {
pn.printNumber(1);
}
}, "Thread-1");
Thread t2 = new Thread(() -> {
while (true) {
pn.printNumber(2);
}
}, "Thread-2");
Thread t3 = new Thread(() -> {
while (true) {
pn.printNumber(3);
}
}, "Thread-3");
t1.start();
t2.start();
t3.start();
}
}
2、代码分析
基于上面代码分析,代码流程与题目1的逻辑基本一致,但也存在一些差异。
a.当number= n时,打印数字,并对number % 后取模后再+1。
b.创建线程使,在Thread类带参构造方法中while(true)实现线程的无限打印。