【Java】Callable,Runnable比较及用法
1、Runnable和Callable的区别
(1) Callable规定的方法是 call(), Runnable规定的方法是 run()。
(2) Callable的任务执行后可返回值,而 Runnable的任务是不能返回值。
(3) call方法可以抛出异常, run方法不可以。
(4)运行 Callable任务可以拿到一个 Future对象
Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get方法来获取结果,如果线程没有执行完, Future.get()方法可能会阻塞当前线程的执行;如果线程出现异常, Future.get()会 throws InterruptedException或者 ExecutionException;如果线程已经取消,会跑出 CancellationException。取消由 cancel方法来执行。
isDone确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future但又不提供可用的结果,则可以声明 Future <?> 形式类型、并返回null作为底层任务的结果。
Future接口的定义如下:
Future模式在请求发生时,会先产生一个 Future凭证给发出请求的客户,它的作用就像是 Proxy物件,同时,由一个新的执行线程持续进行目标物件的生成( Thread - Per - Message),真正的目标物件生成之后,将之设定至 Future之中,而当客户端真正需要目标物件时,目标物件也已经准备好,可以让客户提取使用。
结合 JDK的 Future来看,就是你 run线程后,你可以把线程的返回值赋给 Future并返回一个 Future对象。这时你可以立即拿到这个对象,然后进行下面的逻辑。但是如果你要 get这个 Future中的线程结果,就会被阻塞直到线程结束。
相当于现在的期房,你把手续和钱都交上去了,就可以马上拿到合同,但只有合同没有房子。这个时候你已经是有房一族了,你可以先去买家电买装修(走下面的其他逻辑)。但是你要把家电和装修放进去,就必须等到房子完工(阻塞)。
2、Callable实现:
submit方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化,可以用isDone()的方法来查询Future是否已经完成。当任务完成是,它具有一个结果,可以调用get()方法来获取该结果。
package zeze; import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; /***
*
* @ClassName: EbayMultiplyThreadCheck
* @Description: TODO
* @author zeze
* @date 2017年2月16日 上午8:49:46
*
*/
public class EbayMultiplyThreadCheck {
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(10);
ArrayList<Future<String>> results = new ArrayList<Future<String>>(); for (int i = 0; i < 10; i++) {
String email = "asd" + i + "@qq.com";
results.add(exec.submit(new TaskWithResult(email)));
} boolean isDone = false;
while (!isDone) {
isDone = true;
for (Future<String> future : results) {
if (!future.isDone()) {
isDone = false;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
break;
}
}
}
exec.shutdown();
}
} class TaskWithResult implements Callable<String> { private String email; public TaskWithResult(String email) {
this.email = email;
} @Override
public String call() {
System.out.println(email);
return null;
} }
3、Runnable 实现
/**
* @Title: RunnableDemo.java
* @Package zeze
* @Description: TODO(用一句话描述该文件做什么)
* @author A18ccms A18ccms_gmail_com
* @date 2017年3月13日 下午4:08:09
* @version V1.0
*/
package zeze; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import javafx.animation.Animation.Status; /**
* @ClassName: RunnableDemo
* @Description: TODO
* @author zeze
* @date 2017年3月13日 下午4:08:09
*
*/
public class RunnableDemo implements Runnable { protected int countDown = 10;
private static int taskCount = 0;
private final int id = taskCount++; public RunnableDemo() {
} public RunnableDemo(int countDown) {
this.countDown = countDown;
} public String status() {
return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff!") + ").";
} @Override
public void run() {
while (countDown-- > 0) {
System.out.print(status());
Thread.yield();// 将CPU从一个线程转移给另一个线程
}
} public static void main(String[] args) { System.out.println("这个任务的run()不是单独的线程驱动,是在main()中直接调用");
RunnableDemo launch = new RunnableDemo();
launch.run();
System.out.println();
System.out.println("************************************"); System.out.println("在新线程中启动任务");
Thread thread = new Thread(new RunnableDemo());
thread.start();
System.out.println("Waiting for LiftOff");
System.out.println("************************************"); System.out.println("添加多个线程去驱动更多的任务");
for (int i = 0; i < 5; i++) {
new Thread(new RunnableDemo()).start();
}
System.out.println("Waiting for LiftOff"); System.out.println("************************************");
System.out.println("使用executor");
ExecutorService exec = Executors.newCachedThreadPool();
exec=Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
exec.execute(new RunnableDemo());
}
exec.shutdown();
} }
【Java】Callable,Runnable比较及用法的更多相关文章
- Callable,Runnable比较及用法
http://blog.csdn.net/xtwolf008/article/details/7713580 http://www.cnblogs.com/whgw/archive/2011/09/2 ...
- Java多线程Runnable与Callable区别与拓展
我们先来分别看一下这两个接口 Runnable: // // Source code recreated from a .class file by IntelliJ IDEA // (powered ...
- java多线程—Runnable、Thread、Callable区别
多线程编程优点 进程之间不能共享内存,但线程之间共享内存非常容易. 系统创建线程所分配的资源相对创建进程而言,代价非常小. Java中实现多线程有3种方法: 继承Thread类 实现Runnable接 ...
- Callable,Runnable的区别及用法
编写多线程程序一般有三种方法,Thread,Runnable,Callable. Runnable和Callable的区别是: (1)Callable规定的方法是call(),Runnable规定的方 ...
- Java线程—-Runnable和Callable的区别和联系
Java 提供了三种创建线程的方法 1.继承Thread接口 public class Thread2Thread { public static void main(String[] args) { ...
- java中Runnable和Callable的区别
文章目录 运行机制 返回值的不同 Exception处理 java中Runnable和Callable的区别 在java的多线程开发中Runnable一直以来都是多线程的核心,而Callable是ja ...
- java多线程管理 concurrent包用法详解
我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,当然也有一些开源的框架提供了这些功能,但是这些依然没有JDK自带的功能使用起来方便.而当针对高质量 ...
- Callable, Runnable, Future, FutureTask
Java并发编程之Callable, Runnable, Future, FutureTask Java中存在Callable, Runnable, Future, FutureTask这几个与线程相 ...
- Java Callable接口、Runable接口、Future接口
1. Callable与Runable区别 Java从发布的第一个版本开始就可以很方便地编写多线程的应用程序,并在设计中引入异步处理.Thread类.Runnable接口和Java内存管理模型使得多线 ...
随机推荐
- exception Access restriction: The type 'BASE64Encoder' is not API
Created by Marydon on 1.情景展示 在eclipse中切换jdk版本后,报错信息为:exception Access restriction: The type 'BASE6 ...
- ORACLE-SQL(一)
迁移时间:2017年6月1日10:02:43 CreateTime--2017年6月1日09:59:30Author:Marydon 一.SQL语句 (一)基础篇 1.1.1 where 子句 1 ...
- 感谢CSDN赠送的图书和杂志(5月份)
互联网的精神就是开放.就是分享.在分享的同一时候.我们也会收获到意外的回报. 近期.因为我在5月份发表了14篇博文,因此CSDN赠送了一本图书<软件系统架构>(本人自己选的)和一本< ...
- 优股社区logo
- Centos下cacti的安装
介绍 Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具.Cacti是通过 snmpget来获取数据,使用 RRDtool绘画图形.它提供了非常强大的数据和 ...
- PHP-中文在计算机中的存储
经常我们打开外国网站的时候出现乱码,又或者打开很多非英语的外国网站的时候,显示的都是口口口口口的字符, WordPress程序是用的UTF-8,很多cms用的是GB2312. ● 为什么有这么多编码? ...
- windows named pipe 客户端 服务器
可以实现多客户端对一服务端,服务端为客户端提供服务. 其实一服务端对应每一个client pipe都新建立了一个pipe.windows允许建立多个同名pipe 效果: 服务端代码: #define ...
- sudo: Cannot execute /usr/local/bin/zsh: No such file or directory 问题
参考:sudo: Cannot execute /usr/local/bin/zsh: No such file or directory 之前在美化Ubuntu的时候,下了个zsh,但是忘记改配置文 ...
- 保存已登录plsql developer的用户名和密码
1.保存用户名 tools -> Preferences -> User Interface - Options 勾选 Autosave username . 保存 2.保存密码 tool ...
- Android ——真机调试
1. 设置android手机为USB调试模式.步骤: menu---> 设置 ---> 应用程序 ---> 开发 , 选择[USB调试] 2. 用USB连接手机和电脑,并确保成功.步 ...