Callable是类似于Runnable的接口,实现Callable的类和实现Runnable的类都是可被其他线程执行的任务。
优点:有返回值
缺点:实现繁琐
简单实现:
CallableAndFuture.java
/** * 简单实现 * * @author :liuqi * @date :2018-06-13 11:10. */ public class CallableAndFuture { static class MyThread implements Callable<String> { @Override public String call() throws Exception { return "Hello world"; } } public static void main(String[] args) { ExecutorService threadPool = Executors.newSingleThreadExecutor(); Future<String> future = threadPool.submit(new MyThread()); try { System.out.println(future.get()); } catch (Exception e) { } finally { threadPool.shutdown(); } } }
运行结果:
Hello world
进阶:
Race.java
/** * 实现callable类 * * @author :liuqi * @date :2018-06-13 10:13. */ public class Race implements Callable<Integer> { private String name; private long time; private boolean flag = true; // 步数 private int step = 0; public Race(){ } public Race(String name,int time){ super(); this.name = name; this.time = time; } @Override public Integer call() throws Exception { while(flag){ Thread.sleep(time); step++; } return step; } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getTime() { return time; } public void setTime(long time) { this.time = time; } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public int getStep() { return step; } public void setStep(int step) { this.step = step; } }
Demo05.java
/** * 使用collable接口创建线程 * * @author :liuqi * @date :2018-06-13 10:22. */ public class Demo05 { public static void main(String[] args) throws InterruptedException,ExecutionException { // 创建两个线程 ExecutorService ser = Executors.newFixedThreadPool(2); Race tortoise = new Race("乌龟",1000); Race rabbit = new Race("兔子",500); // 获取future对象 Future<Integer> result1 = ser.submit(tortoise); Future<Integer> result2 = ser.submit(rabbit); // 2秒 Thread.sleep(2000); // 停止线程体循环 tortoise.setFlag(false); rabbit.setFlag(false); // 获取值 int num1 = result1.get(); int num2 = result2.get(); System.out.println("乌龟跑了 " + num1 + "步"); System.out.println("兔子跑了 " + num2 + "步"); // 停止服务 ser.shutdownNow(); } }
运行结果:
乌龟跑了 3步
兔子跑了 5步
lamda表达式:
FutureTask<Integer> ft = new FutureTask<Integer>( ()-> { for(int a=0; a>1000; a++){ list.add(a); System.out.println(Thread.currentThread().getName() + ", a=" + a); } return list.size(); }); new Thread(ft, "thread 3").start();
(FutureTask 实现 RunnableFuture 继承 Runnable)
代码地址:https://github.com/yuki9467/TST-javademo/tree/master/src/main/thread
Callable和Runnable有几点不同:
1.Callable规定方法是call(),而Runnable规定方法是run();
2.Callable任务执行后可返回值,而Runnable不能返回值;
3.call()可抛出异常,而run()不能抛出异常;
4.运行Callable任务可拿到一个Future对象,Future表示异步计算的结果,通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。