如何让 10 个线程按照顺序打印 0123456789?
-
设定一个 orderNum,每个线程执行结束之后,更新 orderNum,指明下一个要执行的线程。并且唤醒所有的等待线程。
-
在每一个线程的开始,要 while 判断 orderNum 是否等于自己的要求值!!不是,则 wait,是则执行本线程。
while(顺序不匹配){
wait
}
update orderNum
import java.util.ArrayList;
import java.util.List;
public class thredSortedPrint {
public static void main(String[] args) {
//创建10个线程
List<myThread> list = new ArrayList<myThread>();
for(int i=10;i>0;i--){
myThread thread = new myThread(i);
thread.start();
}
}
//创建一个内部静态类
static class myThread extends Thread{
public int Num;
static int orderNum = 1;
//创建一个静态的object类作为共同的互斥锁资源
static final Object object = new Object();
public myThread (int num){
this.Num = num;
};
@Override
public void run(){
synchronized (object){
//顺序不匹配则等待,并让出锁资源
while(Num != orderNum){
try {
System.out.println(Thread.currentThread().getName()+":wait");
//锁是object,用object.wait(),当前线程被阻塞,进入等待队列,同时释放互斥锁object
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//匹配则输出打印,更新orderNum,并通知所有线程。
System.out.println(Thread.currentThread().getName()+":"+Num);
orderNum++;
//通知互斥锁的等待队列
object.notifyAll();
}
}
}
}
运行并查看结果,如下。
Thread-0:wait
Thread-1:wait
Thread-3:wait
Thread-4:wait
Thread-7:wait
Thread-8:wait
Thread-2:wait
Thread-6:wait
Thread-5:wait
Thread-9:1
Thread-5:wait
Thread-6:wait
Thread-2:wait
Thread-8:2
Thread-7:3
Thread-4:wait
Thread-3:wait
Thread-1:wait
Thread-0:wait
Thread-2:wait
Thread-6:4
Thread-5:5
Thread-2:wait
Thread-0:wait
Thread-1:wait
Thread-3:wait
Thread-4:6
Thread-3:7
Thread-1:wait
Thread-0:wait
Thread-2:8
Thread-0:wait
Thread-1:9
Thread-0:10
补充:如果通知等待队列的语句改成 object.notify(),可能会导致所有等待的线程都处于等待状态,应该被唤醒的线程没有机会再被唤醒。如下,启动的线程争抢CPU资源,如果打印顺序刚好匹配,则执行并随机通知一个处于等待队列的线程。但是若所有线程都启动了,除去已执行完的线程,剩下的都在队列里,这时候Thread-8执行完后随机通知,被通知到恰好是Thread-3,而此时应该被通知的是Thread-7。Thread-3因打印顺序不匹配,进入等待队列。这时候剩余所有线程都在队列里,也就没有线程会被通知并执行了,形成了活锁。
//通知互斥锁的等待队列
object.notify();
Thread-2:wait
Thread-3:wait
Thread-7:wait
Thread-6:wait
Thread-1:wait
Thread-5:wait
Thread-9:1
Thread-2:wait
Thread-0:wait
Thread-4:wait
Thread-8:2
Thread-3:wait
运用jconsole工具查看线程执行情况 : https://blog.csdn.net/Henry_Lin_Wind/article/details/103408654
剩余的线程全部在等待,但是并没有死锁,所以要慎重使用notify()。