如何让 10 个线程按照顺序打印 0123456789
如何让 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工具查看线程执行情况 :
剩余的线程全部在等待,但是并没有死锁,所以要慎重使用notify()。
那什么时候可以使用 notify() 呢?需要满足以下三个条件: 那什么时候可以使用 notify() 呢?需要满足以下三个条件:
1. 所有等待线程拥有相同的等待条件; 1. 所有等待线程拥有相同的等待条件;
2. 所有等待线程被唤醒后,执行相同的操作; 2. 所有等待线程被唤醒后,执行相同的操作;
3. 只需要唤醒一个线程。 3. 只需要唤醒一个线程。
上一篇:
IDEA上Java项目控制台中文乱码