java callable创建异步线程且有返回值
java中有三种不同的方式创建异线程,如下
继承 Thread 类
实现 Runnable 接口
覆写Callable接口实现多线程(JDK1.5)//有返回值
本文简述callable方式异步线程的实现,
Callable与Runable的区别
(1)Callable执行业务方法是call(),而Runnable执行业务方法是run()。
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。Callable任务返回Future对象。即:Callable和Future一个产生结果,一个拿到结果
(3)call()方法可抛出异常,而run()方法是不能抛出异常的。
(4)运行Callable任务可拿到一个Future对象。
callable与Runable实现的代码示例区别:
static class MyThread implements Callable<String> { @Override public String call() throws Exception { Thread.sleep(5000);//模拟耗时操作 return "Hello world"; //有返回值 } } static class MyThread2 implements Runnable { @Override public void run() { System.out.println("androidos.net"); //Runable没有返回值 } } public static void main(String[] args) { ExecutorService threadPool = Executors.newSingleThreadExecutor(); System.out.println("------------------start"); Future<String> future = threadPool.submit(new MyThread()); //threadPool.submit(new MyThread2()); try { //子线程是异步执行的,主线程休眠等待子线程执行完成,子线程执行完成后唤醒主线程,主线程获取任务执行结果后退出。 String result = future.get(5100, TimeUnit.MILLISECONDS); System.out.println(result); System.out.println("------------------end"); }catch (TimeoutException e) {// 超时异常 System.out.println("TimeoutException"); future.cancel(true); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { threadPool.shutdown(); } }
如果使用不带等待时间限制的get方法时,子线程执行异常了并不会导致主线程的长期阻塞,因为子线程执行异常时其异常会被捕获,然后修改自身任务的状态为异常结束并唤醒等待中的主线程,get方法判断任务状态发生变更后就终止等待了,并抛出异常,
示例2
public static void main(String[] args){ int timeout = 2; ExecutorService executor = Executors.newSingleThreadExecutor(); Boolean result = false; Future<Boolean> future = executor.submit(new TaskThread("开始执行异步程序处理业务")); try { result = future.get(timeout, TimeUnit.SECONDS); System.out.println("异步线程任务执行的返回结果: "+result); } catch (InterruptedException e) { System.out.println("线程中断出错。"); future.cancel(true);// 中断执行此任务的线程 } catch (ExecutionException e) { System.out.println("线程服务出错。"); future.cancel(true); } catch (TimeoutException e) { System.out.println("业务耗时超时。"); future.cancel(true); }finally{ System.out.println("线程服务关闭。"); executor.shutdown(); } } static class TaskThread implements Callable<Boolean> { private String t; public TaskThread(String temp){ this.t= temp; } public Boolean call() { //模拟耗时业务 for(int i=0;i<=50;i++){ if(i==50){ System.out.println(t); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (Thread.interrupted()){ return false; } } System.out.println("业务处理线束"); return true; } } }
如上:Callable任务只能通过 ExecutorService.submit方法来调用。submit方法会返回Future类型的对象,可以通过isDone方法来检查任务是否完成,通过get方法来获取任务的返回值。当然也可以不调用isDone方法而直接调用get方法,这时get方法将阻塞直到任务完成得到返回值,
注意:调用Future类的get方法为堵塞当前线程,如你在主线程中调用了Future的get方法,那么此方法就会堵塞主线程,get方法之后的逻辑是执行不了,直至有返回值才会往下执行,所以有返回的值创建异线程Callable方法,如果你要需要获取返回值 ,且是在主线程中获取返回值 ,它的作用与Thread.join()方法是一样的,类似线程插队,不全是多线程异常执行。
Android源码中callable示例代码:
private int getWfcMode(ImsMmTelManager imsMmTelManager) throws InterruptedException, ExecutionException, TimeoutException { final FutureTask<Integer> wfcModeTask = new FutureTask<>(new Callable<Integer>() { @Override public Integer call() { return imsMmTelManager.getVoWiFiModeSetting(); } }); final ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(wfcModeTask); return wfcModeTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); }
使用FutureTask与Callable组合有返回的多线程
// 定义普通实现Callable接口,返回一个String类型的结果,可以是定义为其他任何类型的返回值类型 class MyCallable implements Callable<String> { @Override public String call() throws Exception { //sleep();//模拟业务逻辑 return 0; } } public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable callable = new MyCallable(); //使用 FutureTask 用于获取线程执行结果 FutureTask<String> futureTask = new FutureTask<>(callable); Thread thread = new Thread(futureTask); thread.start(); //获取线程执行的结果 String result = futureTask.get(); }
Future 与FutureTask的简述说明
Future是一个接口表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。
Future提供了get()、cancel()、isCancel()、isDone()四种方法,表示Future有三种功能:
1、判断任务是否完成
2、中断任务
3、获取任务执行结果
FutureTask
FutureTask是Future的实现类,它提供了对Future的基本实现。可使用FutureTask包装Callable或Runnable对象,
因为FutureTask实现了Runnable,所以也可以将FutureTask提交给Executor。
评论