線程的執(zhí)行是隨機(jī)的茫经,由CPU控制浸须,但是我們可以通過以下的方法對多線程進(jìn)行可控順序的執(zhí)行:
1.使用join方法:讓主線程等待子線程的執(zhí)行完成
工作原理是:在當(dāng)前線程調(diào)用其它線程的join會讓當(dāng)前線程阻塞等待join線程的執(zhí)行完成,不停檢查thread是否存活正什,如果存活則讓當(dāng)前線程一直wait光酣,直到thread線程終止厦瓢,線程的this.notifyAll 就會被調(diào)用高镐。
public classTest{
public static void main(String[] args) throws InterruptedException {
? ? ? ? Thread t1 = new Thread(new MyThread1());
? ? ? ? Thread t2 = new Thread(new MyThread2());
? ? ? ? Thread t3 = new Thread(new MyThread3());
? ? ? ? t1.start();
? ? ? ? t1.join();
? ? ? ? t2.start();
? ? ? ? t2.join();
? ? ? ? t3.start();
? ? }
}
classMyThread1implementsRunnable{? ? @Override
? ? public void run() {
? ? ? ? System.out.println("I am thread 1");
? ? }
}classMyThread2implementsRunnable{? ? @Override
? ? public void run() {
? ? ? ? System.out.println("I am thread 2");
? ? }
}classMyThread3implementsRunnable{? ? @Override
? ? public void run() {
? ? ? ? System.out.println("I am thread 3");
? ? }
}
2.使用CountDownLatch溉旋,它與join效果是一樣的畸冲,都是用來阻塞其他線程的執(zhí)行嫉髓,等待本線程執(zhí)行完观腊,但是它采用的是計(jì)數(shù)器方式,如果發(fā)現(xiàn)計(jì)數(shù)器為0就結(jié)束阻塞繼續(xù)執(zhí)行下去算行。他們的區(qū)別在于join需要等待線程的完全執(zhí)行完才會notifyall其他線程梧油,而CountDownLatch不需要,它可以分階段州邢,只要計(jì)數(shù)器為0儡陨。?countDownLatch.countDown();?
public?class?Worker?extends?Thread?{??
//工作者名??
private?String?name;??
//第一階段工作時間??
private?long?time;??
private?CountDownLatch?countDownLatch;??
public?Worker(String?name,?long?time,?CountDownLatch?countDownLatch)?{??
this.name?=?name;??
this.time?=?time;??
this.countDownLatch?=?countDownLatch;??
????}??
@Override??
public?void?run()?{??
//?TODO?自動生成的方法存根??
try?{??
System.out.println(name+"開始工作");??
????????????Thread.sleep(time);??
System.out.println(name+"第一階段工作完成");??
????????????countDownLatch.countDown();??
Thread.sleep(2000);?//這里就姑且假設(shè)第二階段工作都是要2秒完成??
System.out.println(name+"第二階段工作完成");??
System.out.println(name+"工作完成,耗費(fèi)時間="+(time+2000));??
}catch?(InterruptedException?e)?{??
//?TODO?自動生成的?catch?塊??
????????????e.printStackTrace();??
????????}?????
????}??
}??
package?com.concurrent.test5;??
import?java.util.concurrent.CountDownLatch;??
public?class?Test?{??
public?static?void?main(String[]?args)?throws?InterruptedException?{??
//?TODO?自動生成的方法存根??
CountDownLatch?countDownLatch?=new?CountDownLatch(2);??
Worker?worker0?=new?Worker("worker0",?(long)?(Math.random()*2000+3000),?countDownLatch);??
Worker?worker1?=new?Worker("worker1",?(long)?(Math.random()*2000+3000),?countDownLatch);??
Worker?worker2?=new?Worker("worker2",?(long)?(Math.random()*2000+3000),?countDownLatch);??
????????worker0.start();??
????????worker1.start();??????
????????countDownLatch.await();??
System.out.println("準(zhǔn)備工作就緒");??
????????worker2.start();??
????}??
}??
3.使用Excutors.newSingleThreadExecutor():這是單線程的線程池量淌,底層原理是一個先進(jìn)先出的隊(duì)列
public classTest{ private static ExecutorService executor = Executors.newSingleThreadExecutor();
? ? public static void main(String[] args) throws InterruptedException {
? ? ? ? Thread t1 = new Thread(new MyThread1());
? ? ? ? Thread t2 = new Thread(new MyThread2());
? ? ? ? Thread t3 = new Thread(new MyThread3());
? ? ? ? executor.submit(t1);
? ? ? ? executor.submit(t2);
? ? ? ? executor.submit(t3);
? ? ? ? executor.shutdown();
? ? }
}
classMyThread1implementsRunnable{? ? @Override
? ? public void run() {
? ? ? ? System.out.println("I am thread 1");
? ? }
}
classMyThread2implementsRunnable{? ? @Override
? ? public void run() {
? ? ? ? System.out.println("I am thread 2");
? ? }
}
classMyThread3implementsRunnable{? ? @Override
? ? public void run() {
? ? ? ? System.out.println("I am thread 3");
? ? }
}