1、通过join()方法指定顺序
当然,thread的join方法实现多线程顺序执行有两种方式,一种是在子线程内部调用join()方法,另一种是直接在主线程调用join()方法;写法上是主线程上调用join()更直观,谁先执行谁后执行一目了然。子线程内部调用的话,相对的要注意调用的顺序。
1.子线程内部调用join()
public class ThreadJoinDemo {
public static void main(String[] args) throws InterruptedException {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("打开冰箱!");
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("拿出一瓶牛奶!");
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("关上冰箱!");
}
});
//下面三行代码顺序可随意调整,程序运行结果不受影响,因为我们在子线程中通过“join()方法”已经指定了运行顺序(还有一个原因就是之前说的多线程的生命周期中有就绪状态,需要等待cpu调度,start并不意味着运行状态)。
thread3.start();
thread2.start();
thread1.start();
}
}
2.在主线程中通过join()方法指定顺序
public class ThreadMainJoinDemo {
public static void main(String[] args) throws InterruptedException {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("打开冰箱!");
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("拿出一瓶牛奶!");
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("关上冰箱!");
}
});
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
}
}
2、使用jdk5推出的线程池Executors创建单例的方法
public class ThreadPoolDemo {
static ExecutorService executorService = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("打开冰箱!");
}
});
final Thread thread2 =new Thread(new Runnable() {
@Override
public void run() {
System.out.println("拿出一瓶牛奶!");
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("关上冰箱!");
}
});
executorService.submit(thread1);
executorService.submit(thread2);
executorService.submit(thread3);
executorService.shutdown(); //使用完毕记得关闭线程池
}
}
3、CountDownLatch(倒计数)类
CountDownLatch类的特点就是可以初始化设置一个state的值,每次调用countDown()方法进行减一,如果state没有减小到0就会被await()方法一直阻塞。利用CountDownLatch方法可以实现和join()方法子线程运用一样的妙处。当然,CountDownLatch类的缺点是state不能重置,只能初始化一次,意思就是减小到0后,就没用了。。。不能加回去。
public class ThreadCountDownLatchDemo {
private static CountDownLatch countDownLatch1 = new CountDownLatch(1);
private static CountDownLatch countDownLatch2 = new CountDownLatch(1);
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("打开冰箱!");
countDownLatch1.countDown();
}
});
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
countDownLatch1.await();
System.out.println("拿出一瓶牛奶!");
countDownLatch2.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
final Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
countDownLatch2.await();
System.out.println("关上冰箱!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//下面三行代码顺序可随意调整,程序运行结果不受影响
thread3.start();
thread1.start();
thread2.start();
}
}