使用Callable和Future接口创建线程
具体是创建Callable接口的实现类,并实现clall()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。
看着好像有点复杂,直接来看一个例子就清晰了。
public class ThreadTest {
public static void main(String[] args) {
Callable<Integer> myCallable = new MyCallable(); // 创建MyCallable对象
FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //使用FutureTask来包装MyCallable对象
for (int i = ; i < ; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == ) {
Thread thread = new Thread(ft); //FutureTask对象作为Thread对象的target创建新的线程
thread.start(); //线程进入到就绪状态
}
}
System.out.println("主线程for循环执行完毕..");
try {
int sum = ft.get(); //取得新创建的新线程中的call()方法返回的结果
System.out.println("sum = " + sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<Integer> {
private int i = ;
// 与run()方法不同的是,call()方法具有返回值
@Override
public Integer call() {
int sum = ;
for (; i < ; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
sum += i;
}
return sum;
}
}
首先,我们发现,在实现Callable接口中,此时不再是run()方法了,而是call()方法,此call()方法作为线程执行体,同时还具有返回值!在创建新的线程时,是通过FutureTask来包装MyCallable对象,同时作为了Thread对象的target。那么看下FutureTask类的定义:
public class FutureTask<V> implements RunnableFuture<V> {
//....
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
于是,我们发现FutureTask类实际上是同时实现了Runnable和Future接口,由此才使得其具有Future和Runnable双重特性。通过Runnable特性,可以作为Thread对象的target,而Future特性,使得其可以取得新创建线程中的call()方法的返回值。
执行下此程序,我们发现sum = 4950永远都是最后输出的。而“主线程for循环执行完毕..”则很可能是在子线程循环中间输出。由CPU的线程调度机制,我们知道,“主线程for循环执行完毕..”的输出时机是没有任何问题的,那么为什么sum =4950会永远最后输出呢?
原因在于通过ft.get()方法获取子线程call()方法的返回值时,当子线程此方法还未执行完毕,ft.get()方法会一直阻塞,直到call()方法执行完毕才能取到返回值。
上述主要讲解了三种常见的线程创建方式,对于线程的启动而言,都是调用线程对象的start()方法,需要特别注意的是:不能对同一线程对象两次调用start()方法。
使用Callable和Future接口创建线程的更多相关文章
- 通过Callable接口创建线程
通过Callable接口创建线程 一.前言 Java中创建线程的方式有四中,前两种在前面我已经详细介绍过了(Runnable和Thread),不清楚的朋友们可看这里: Java多线程之线程的启动以及J ...
- 实现Callable接口创建线程
创建执行线程有四种方式: 实现implements接口创建线程 继承Thread类创建线程 实现Callable接口,通过FutureTask包装器来创建线程 使用线程池创建线程 下面介绍通过实现Ca ...
- 使用Runnable接口创建线程-3
实现Runnable接口的类必须使用Thread类的实例才能创建线程.通过Runnable接口创建线程分为两步: 1. 将实现Runnable接口的类实例化. 2. 建立一个Thread对象,并将第一 ...
- 使用Runnable接口创建线程
实现Runnable接口的类必须使用Thread类的实例才能创建线程.通过Runnable接口创建线程分为两步: 1.将实现Runnable接口的类实例化. 2.建立一个Thread对象,并将第一步实 ...
- Java多线程:实现API接口创建线程方式详解
先看例子: /**实现Runnable接口创建线程步骤: * 1.创建一个实现Runnable接口的类 * 2.重写Runnable类中抽象的run()方法 * 3.创建实现类的对象 * 4.声明Th ...
- Android(java)学习笔记66:实现Runnable接口创建线程 和 使用Callable和Future创建线程
1. 前面说的线程的实现是新写一个子类继承Thread: 是将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法.接下来可以分配并启动该子类的实例 2. 这里说的方案2是指 ...
- Android(java)学习笔记6:实现Runnable接口创建线程 和 使用Callable和Future创建线程
1. 前面说的线程的实现是新写一个子类继承Thread: 是将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法.接下来可以分配并启动该子类的实例 2. 这里说的方案2是指 ...
- 使用Callable接口创建线程和使用线程池的方式创建线程
1.使用Callable接口的方式实现多线程,这是JDK5.0新增的一种创建多线程的方法 package com.baozi.java2; import java.util.concurrent.Ca ...
- 使用Runnable接口创建线程池
步骤: 创建线程池对象创建 Runnable 接口子类对象提交 Runnable 接口子类对象关闭线程池实例: class TaskRunnable implements Runnable{ @Ove ...
随机推荐
- MAC帧格式、IPV4数据报格式、TCP报文格式、UDP数据报格式
1.MAC帧格式 类型:2字节,指出数据域中携带的数据应交给哪些协议实体处理 校验码:校验数据段(采用32位CRC冗余校验方式进行校验) 2.IPV4数据报 版本:IP协议版本,这里为4 首部长度:占 ...
- 再学Java 之 形参个数可变函数
自Java 5后,Java允许定义形参个数可变的方法,从而允许运行过程中,为方法指定不确定个数的形参. 其定义方法的格式如下: void function_name ( type ... variab ...
- 【转】Entity framework 6 编写的通用数据类
原文:http://blog.csdn.net/laokaizzz/article/details/25730813 准备参考
- 解析xml文件步骤 -- pullparser
1. 初始化一个xml的解析器 XmlPullParser parser = Xml.newPullParser(); 2. 设置解析器的参数 InputStream inputStream = th ...
- 用PopupWindow做下拉框
最近在做下拉框,本来想用spinner,可是spinner达不到项目要求,跟同学同事问了一圈,都在用popwindow, 网上看了一下,popwindow挺简单的,可定制性挺强的,符合我的要求,所以, ...
- redis 迁移工具 redis-port 从阿里云迁移到aws
对于 redis 的 迁移我在网上看到了很多方法,有使用redis-dump 的,有使用 aof导入方式,有rdb文件迁移方式,和redis-port. 由于我是将 redis 从阿里云迁移到AW ...
- java-forkjoin框架的使用
ForkJoin是Java7提供的原生多线程并行处理框架,其基本思想是将大任务分割成小任务,最后将小任务聚合起来得到结果.fork是分解的意思, join是收集的意思. 它非常类似于HADOOP提供的 ...
- JBoss Web和Tomcat的区别
在Web2.0的时代,基于Tomcat内核的JBoss在J2EE应用服务器领域已成为发展最为迅速的应用服务器.这一青出于蓝而胜于蓝的产品与Tomcat的区别又在哪里? 基于Tomcat内核,青胜于蓝. ...
- [HNOI 2018]寻宝游戏
Description 题库链接 给出 \(n\) 个 \(m\) 位的二进制数,在每一个二进制数间插入一个 & 或 | ,第 \(0\) 个数为 \(0\) , \(0,1\) 间也要插入符 ...
- Oracle相关
where 条件中使用=进行限制时,可以返回一个记录集,即可以返回多个记录集