Runnable与Callable 详解
来源:互联网 发布:战舰世界兴登堡数据 编辑:程序博客网 时间:2024/06/13 03:24
Runnable与Callable区别
- Callable规定的方法是 call(), Runnable规定的方法是 run()。
- Callable的任务执行后可返回值,而 Runnable的任务是不能返回值。
- call方法可以抛出异常, run方法不可以。
- 运行 Callable任务可以拿到一个 Future对象
*Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get方法来获取结果,如果线程没有执行完, Future.get()方法可能会阻塞当前线程的执行;如果线程出现异常, Future.get()会 throws InterruptedException或者 ExecutionException;如果线程已经取消,会跑出 CancellationException。取消由 cancel方法来执行。
isDone确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future但又不提供可用的结果,则可以声明 Future
什么是Future?
Future模式在请求发生时,会先产生一个 Future凭证给发出请求的客户,它的作用就像是 Proxy物件,同时,由一个新的执行线程持续进行目标物件的生成( Thread - Per - Message),真正的目标物件生成之后,将之设定至 Future之中,而当客户端真正需要目标物件时,目标物件也已经准备好,可以让客户提取使用。
结合 JDK的 Future来看,就是你 run线程后,你可以把线程的返回值赋给 Future并返回一个 Future对象。这时你可以立即拿到这个对象,然后进行下面的逻辑。但是如果你要 get这个 Future中的线程结果,就会被阻塞直到线程结束。 就相当于购物一样,你下单支付成功之后,一直等待物流,只有等商品送到你手上你才可以进行使用。其他时间你都得等待它。
Runnable 使用
package cn.heh;import java.text.NumberFormat;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class RunnableDemo implements Runnable { //总的车票数 private int total; RunnableDemo(int total) { this.total = total; } //初始车票号码 1 private int num = 1; @Override public void run() { while (true) { synchronized (this) { try { // 任何线程获取"线程锁"以后都要先判断是否还有余票,防止等待的线程多打印车票 if (num > total) return; // 获取当前线程名字 String threadName = Thread.currentThread().getName(); // 格式化票号 String ticketNum = FormatTicketNum(num++); // 打印火车票,休眠10毫秒模拟打印车票时间 Thread.sleep(10); System.out.println(threadName + " 售出火车票No." + ticketNum); // 某线程售完最后一张车票时,放出"车票已售罄"提示 if (num > total) { System.out.println("车票已售罄!"); return; } } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 格式化车票号码 */ static String FormatTicketNum(int num) { NumberFormat nf = NumberFormat.getIntegerInstance(); nf.setMinimumIntegerDigits(3); return nf.format(num); } public static void main(String[] args) { System.out.println("直接调用run()相当于调用本地方法一样并不会启动线程"); RunnableDemo launch = new RunnableDemo(10); launch.run(); System.out.println("************************************"); System.out.println("在新线程中启动任务"); RunnableDemo launch1 = new RunnableDemo(10); Thread thread = new Thread(launch1, "小何"); thread.start(); System.out.println("************************************"); RunnableDemo launch2 = new RunnableDemo(500); for (int i = 0; i < 5; i++) { new Thread(launch2, "售票员" + i).start(); } System.out.println("************************************"); System.out.println("线程池方式单线程允许"); RunnableDemo launch3 = new RunnableDemo(500); ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(launch3); System.out.println("************************************"); System.out.println("线程池方式多线程允许"); RunnableDemo launch4 = new RunnableDemo(500); ExecutorService executorService1 = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService1.execute(launch4); } }}
运行结果就不在这里展示了。至于为什么我会选择后期使用线程池方式执行。其实使用execute执行效果与上面thread.start一样,都不会有结果返回。再看一下下面的代码
Callable使用实例
package cn.heh;import java.text.NumberFormat;import java.util.ArrayList;import java.util.List;import java.util.concurrent.*;public class CallableDemo implements Callable<String> { //总的车票数 private int total; CallableDemo(int total) { this.total = total; } //初始车票号码 1 private int num = 1; @Override public String call() throws Exception { while (true) { synchronized (this) { try { // 任何线程获取"线程锁"以后都要先判断是否还有余票,防止等待的线程多打印车票 if (num > total) return "车票已售罄!"; // 获取当前线程名字 String threadName = Thread.currentThread().getName(); // 格式化票号 String ticketNum = FormatTicketNum(num++); // 打印火车票,休眠10毫秒模拟打印车票时间 Thread.sleep(10);// System.out.println(threadName + " 售出火车票No." + ticketNum); return threadName + " 售出火车票No." + ticketNum; } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 格式化车票号码 */ static String FormatTicketNum(int num) { NumberFormat nf = NumberFormat.getIntegerInstance(); nf.setMinimumIntegerDigits(3); return nf.format(num); } public static void main(String[] args) { ExecutorService exec = Executors.newFixedThreadPool(10); List<Future<Integer>> results = new ArrayList<>(); Callable callable = new CallableDemo(100); for (int i = 0; i < 10; i++) { results.add(exec.submit(callable)); } boolean isDone = false; while (!isDone) { isDone = true; for (Future<Integer> future : results) { if (!future.isDone()) { isDone = false; try { Thread.sleep(1000); } catch (InterruptedException e) { } break; } else { try { System.out.println(future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } } exec.shutdown(); }}
submit()方法回产生Future对象,它用Callable返回结果的特定类型进行了参数化。可以用isDone()方法来查询Future是否已经完成,当任务完成时,它具有一个结果,可以调用get()方法获取该结果。也可以不用isDone()进行检查就直接调用get(),在这种情况下,get()将阻塞,直至结果准备就绪。还可以在试图调用get()来获取结果之前,先调用具有超时的get(),或者调用isDone()来查看任务是否完成。
0 0
- Runnable与Callable 详解
- Runnable与Callable
- Callable与Runnable区别
- Callable接口与Runnable
- Runnable与Callable
- 说说Runnable与Callable
- 多线程 Callable Runnable 与Future
- Runnable&Callable
- java中Runnable与Callable区别
- Callable接口与Runnable接口区别
- Callable接口与Runnable接口的区别
- Runnable, Callable, Future与FutureTask,例程
- 浅谈Runnable与Callable的区别
- Android线程—Callable与Runnable
- Java中的Runnable、Callable、Future、FutureTask的区别与示例
- Java中的Runnable、Callable、Future、FutureTask的区别与示例
- Java中的Runnable、Callable、Future、FutureTask的区别与示例
- Java中的Runnable、Callable、Future、FutureTask的区别与示例
- PPM文件格式详解
- JS获取元素样式、绑定解除事件函数兼容
- Hexo+github搭建个人博客
- UVA
- Hadoop Mapreduce分区、分组、二次排序过程详解
- Runnable与Callable 详解
- butterknife的使用
- PCA原理及其R实现
- BZOJ 4004: [JLOI2015]装备购买
- 运算符 流控制 test echo
- 在mac上安装php7.1
- 秒杀系统架构优化思路
- OpenProcess调用失败,GetLastError返回5
- wampserver访问localhost显示iis