版权声明:本文为博主原创文章,未经博主容许不得转载
源码:github.com/AnliaLee
你们要是看到有错误的地方或者有啥好的建议,欢迎留言评论html
在 大话Android多线程(一) 一文中,咱们聊了建立线程的两种方式(继承Thread和实现Runnable接口),并比对了它们的区别。本章咱们将介绍第三种方式 —— 经过实现Callable接口来建立线程java
往期回顾
大话Android多线程(一) Thread和Runnable的联系和区别
大话Android多线程(二) synchronized使用解析
大话Android多线程(三) 线程间的通讯机制之Handlerandroid
咱们先简单举个栗子,看看经过实现Callable接口来建立线程的方式和以前两种有什么区别git
某日,高铁站前,老C和他儿子作别,儿子:“爸爸,你走吧。”老C望了望路边的小摊,说道github
说完老C便走去小摊买橘子了(实现Callable接口,重写call()方法)编程
public static class TestCallable implements Callable{
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + ":我买几个橘子去。你就在此地,不要走动" + " 时间:" + getTime());
Thread.sleep(2000);//模拟买橘子的时间
return Thread.currentThread().getName() + ":我买完橘子回来了" + " 时间:" + getTime();
}
}
复制代码
儿子天然是乖乖站在原地等爸爸买橘子多线程
public class CallableTest {
//省略部分代码...
public static void main(String args[]){
TestCallable callable = new TestCallable();
FutureTask<String> futureTask = new FutureTask<String>(callable);
Thread thread1 = new Thread(futureTask, "爸爸");
thread1.start();
System.out.println("儿子还没收到橘子" + " 时间:" + getTime());//验证主线程的执行状况
try{
System.out.println(futureTask.get());
System.out.println("儿子收到橘子" + " 时间:" + getTime());//验证主线程的执行状况
}catch (InterruptedException | ExecutionException e){
}
}
}
复制代码
正常买到橘子的运行结果以下并发
若是没买到橘子呢(咱们尝试在call()方法中抛出异常,而后在调用get()方法时进行捕获)?app
public static class TestCallable implements Callable{
private int ticket = 10;
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + ":我买几个橘子去。你就在此地,不要走动" + " 时间:" + getTime());
Thread.sleep(2000);//模拟买橘子的时间
System.out.println(Thread.currentThread().getName() + ":橘子卖完了" + " 时间:" + getTime());
throw new NullPointerException("橘子卖完了");
}
}
public static void main(String args[]){
TestCallable callable = new TestCallable();
FutureTask<String> futureTask = new FutureTask<String>(callable);
Thread thread1 = new Thread(futureTask, "爸爸");
thread1.start();
System.out.println("儿子站在原地" + " 时间:" + getTime());//验证主线程的执行状况
try{
System.out.println(futureTask.get());
System.out.println("儿子收到橘子" + " 时间:" + getTime());//验证主线程的执行状况
}catch (InterruptedException | ExecutionException e){
System.out.println("儿子没收到橘子" + " 时间:" + getTime());//验证主线程的执行状况
}
}
复制代码
另外须要注意的是,爸爸的钱只够买一袋橘子(任务只能执行一次)异步
public static void main(String args[]){
TestCallable callable = new TestCallable();
FutureTask<String> futureTask = new FutureTask<String>(callable);
Thread thread1 = new Thread(futureTask, "爸爸去了第一个摊位");
Thread thread2 = new Thread(futureTask, "爸爸去了第二个摊位");
Thread thread3 = new Thread(futureTask, "爸爸去了第三个摊位");
thread1.start();
thread2.start();
thread3.start();
System.out.println("儿子站在原地" + " 时间:" + getTime());//验证主线程的执行状况
try{
System.out.println(futureTask.get());
System.out.println("儿子收到橘子" + " 时间:" + getTime());//验证主线程的执行状况
}catch (InterruptedException | ExecutionException e){
System.out.println("儿子没收到橘子" + " 时间:" + getTime());//验证主线程的执行状况
}
}
复制代码
总结上面的案例:
Future是一个接口,而FutureTask实现了RunnableFuture接口,RunnableFuture继承了Runnable接口和Future接口(继承关系见下图)
FutureTask用于异步获取执行结果或取消执行任务的场景,它的主要功能有:
- 能够判断任务是否完成
- 能够获取任务执行结果
- 能够中断任务
更详细的源码解析及用法能够看下这几篇博客
Java并发编程:Callable、Future和FutureTask原理解析
Java FutureTask 源码分析 Android上的实现
FutureTask的用法及两种经常使用的使用场景
区别于实现Runnable接口建立线程的方式,以上这两点功能Runnable就没法实现了
在UI线程中使用时(尤为是后续还有更新UI的操做)要特别注意这点,以避免形成界面卡顿。那么要如何处理这种多线程执行耗时任务,等待结果,而后再更新UI的状况呢?没错!就是使用咱们上一章讲到的Handler,Android系统提供的AsyncTask也正是用到了这一方式实现了异步操做,咱们将在后续的章节详细介绍AsyncTask
此外,除了直接new一个Thread,咱们还能够利用线程池结合Callable执行多线程任务
public static void main(String args[]){
TestCallable callable = new TestCallable();
ExecutorService executor = Executors.newCachedThreadPool();
Future<String> future = executor.submit(callable);
//或者
//FutureTask<String> future = new FutureTask<String>(callable);
//executor.execute(future);
System.out.println("儿子站在原地" + " 时间:" + getTime());//验证主线程的执行状况
try{
System.out.println(future.get());
System.out.println("儿子收到橘子" + " 时间:" + getTime());//验证主线程的执行状况
}catch (InterruptedException | ExecutionException e){
System.out.println("儿子没收到橘子" + " 时间:" + getTime());//验证主线程的执行状况
}
}
复制代码
那么线程池又是啥?留到下一章咱们再“大话”一番吧
本篇博客到此结束,若你们有啥疑问或建议欢迎留言评论,感激涕零。若是以为写得还不错麻烦点个赞,大家的支持是我最大的动力~