有t1,t2,t3三个线程,实现t1,t2线程同步执行,然后再执行t3线程,使用Java实现该程序
这个面试题经常遇到,首先从题目上看,就知道考察的是多线程方面知识,看到这个题目的时候,想到了使用CountDownLatch这个计数器来实现,因为它的原理就是让一个线程或多个线程去等待另外线程执行完毕后再执行的,本篇文章,我打算用两种方式去实现这个题目,分别是使用CountDownLatch和Future来实现。
1、利用CountDownLatch
如果第一次听说CountDownLatch的话,也没用关系,我会用最通俗易懂的话去介绍。
CountDownLatch其实就是一个计数器,在new这个对象的时候,需要在CountDownLatch的参数中传递一个int类型的数字,并且这个int类型必须大于等于0。
而这个count值传递给Sync后,就会调用一个setState方法,这是AQS里面的内容,过多的我就不去讲述,如果有兴趣的话可以去网上搜一下AQS了解一下。这个state有三种,分别是0、1、大于1,首先0就代表着目前还没有线程去占用这个资源,可以抢占,1代表着目前已经有一个线程抢占着这个资源了,不允许其他线程再占有了,这时其他线程就会被放入到一个双向链表队列进行等待排队(可以去了解一下AQS的等待队列),大于1呢就是说这个资源被重入的次数。所以,利用该状态码值就可以实现线程等待。
接着介绍一下CountDownLatch的常用方法
示例代码
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch c = new CountDownLatch(2);//初始化一个对象,把计数器定为2
new Thread(() -> {
System.out.println("我是线程1");
c.countDown();//计数器减一
}, "t1").start();
new Thread(() -> {
System.out.println("我是线程2");
c.countDown();//计数器减一
}, "t2").start();
c.await();//调用await方法,让线程3等待前两个线程执行完毕
new Thread(() -> {
System.out.println("我是线程3");
}, "t3").start();
}
}
2、利用Future
Future其实就是一个异步任务监视器,可以监视任务的执行,也可以取消任务的执行,同时也可以通过get()方法获取执行后的返回结果。
为了方便演示效果,我使用了有返回结果的Callable来实现。
Future的常用方法
public class FutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//首先创建一个线程池
ExecutorService executorService = Executors.newCachedThreadPool();
//线程池的submit返回值类型就是Future
Future<String> s1 = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(200);//模拟程序运行时间
return "我是线程1";
}
});
Future<String> s2 = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(200);//模拟程序运行时间
return "我是线程2";
}
});
try {
System.out.println(s1.get(1000, TimeUnit.MILLISECONDS));
} catch (TimeoutException e) {
e.printStackTrace();
}
try {
System.out.println(s2.get(1000, TimeUnit.MILLISECONDS));
} catch (TimeoutException e) {
e.printStackTrace();
}
if (s1.isDone() && s2.isDone()) {
Thread.sleep(300);//模拟程序运行时间
System.out.println("我是线程3");
}
executorService.shutdown();
}
}
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员阿龙
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果