线程的执行是随机的,由CPU控制,但是我们可以通过以下的方法对多线程进行可控顺序的执行:
1.使用join方法:让主线程等待子线程的执行完成
工作原理是:在当前线程调用其它线程的join会让当前线程阻塞等待join线程的执行完成,不停检查thread是否存活,如果存活则让当前线程一直wait,直到thread线程终止,线程的this.notifyAll 就会被调用。
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效果是一样的,都是用来阻塞其他线程的执行,等待本线程执行完,但是它采用的是计数器方式,如果发现计数器为0就结束阻塞继续执行下去。他们的区别在于join需要等待线程的完全执行完才会notifyall其他线程,而CountDownLatch不需要,它可以分阶段,只要计数器为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); //这里就姑且假设第二阶段工作都是要2秒完成
System.out.println(name+"第二阶段工作完成");
System.out.println(name+"工作完成,耗费时间="+(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("准备工作就绪");
worker2.start();
}
}
3.使用Excutors.newSingleThreadExecutor():这是单线程的线程池,底层原理是一个先进先出的队列
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");
}
}