【简述】

从java5开始,java提供了Callable接口,这个接口可以是Runnable接口的增强版,

Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能更强大。

【call()方法特点】

1.call()方法可以有返回值

2.call()方法可以声明抛出异常。

【Future接口】

java5提供了Future接口来代表Callable接口里的call()方法的返回值,并为Future接口提供了一个FutureTask实现类,该实现类实现了Future接口,并实现了Runnable接口,所以这样可以作为Thread的target。

在Future接口里定义了一下公共方法来控制它关联的Callable任务。

1. boolean cancel( boolean mayInterruptRunning):试图取消该Future里关联的Callable任务。

2. V get() :返回Callable任务里call()方法的返回值。调用该方法会导致程序阻塞,必须等到子线程结束后才会得到返回值。

3. V get( long timeout, TimeUnit unit ):返回Callable任务里call方法的返回值。该方法然程序最多阻塞timeout和unit指定的时间,如果时间到了Callable没返回值,抛TimeoutException异常。

4.boolean isCancelled():如果Callable任务正常完成前被取消,返回true。

5.boolean isDone():如果Callable任务已完成,则返回true。

【创建和启动线程的步骤】

1.创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法没有返回值,再创建Callable实现类的实例。(从java8开始,可以直接使用Lambda表达式创建Callable对象)。

2.使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。

3.使用FutureTask作为Thread对象的target创建并启动新线程。

4.调用FutureTask对象的get方法来获得子线程执行结束后的返回值。

【示例代码】

package com.Higgin.part01;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; class ThirdThread { } public class Demo3 { public static void main(String[] args) {
//创建Callable对象
ThirdThread rt=new ThirdThread();
//先使用Lambda表达式创建Callable<Integer>对象,
//并使用FutureTask来包装Callable对象
FutureTask<Integer> task=new FutureTask<Integer>((Callable<Integer>)()->{
int i=;
for(;i<;i++){
System.out.println(Thread.currentThread().getName()+"===="+i);
}
//call()方法可以有返回值
return
i;
}); for(int i=;i<;i++){
System.out.println(Thread.currentThread().getName()+"===="+i);
if(i==){
Thread t1=new Thread(task,"有返回值的线程");
t1.start();
}
}
try {
System.out.println("子线程的返回值:"+task.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}

【运行结果】

【总结】

1.红框内的代码是以Callable对象来启动线程的关键代码。首先使用Lambda表达式创建一个Callable对象,然后将该线程包装成一个FutureTask对象。

2.主线程中,当循环变量i=20时,程序启动以FutureTask对象为target的线程。程序最后调用FutureTask对象的get()方法来返回call()方法的返回值---该方法将导致主线程被阻塞,直到call()方法结束并返回为止。

【采用实现Runnable、Callable接口方式创建多线程】

【优点】
1.线程只是实现了Runable接口或者Callable接口,还可以继承其它类。

2.在这种方式下,多个线程可以共享同一个target对象,比较适合多个相同线程来处理同一份资源的情况。

【缺点】

编程略复杂,如果需要访问当前线程,则必须使用Thread currentThread()方法。

【采用继承Thread类来创建多线程】

【优点】

编写简单,如果需要访问当前线程,只需使用this即可获得当前线程。

【缺点】

因为继承了Thread类,所以不能再继承其他父类。

【分析】

一般推荐采用实现Runnable、Callable接口的方式来创建多线程。

04_线程的创建和启动_使用Callable和Future的方式的更多相关文章

  1. 03_线程的创建和启动_实现Runnable接口方式

    [线程的创建和启动的步骤(实现Runnable接口方式)] 1.定义Runnable接口的实现类,并重写其中的run方法.run()方法的方法体是线程执行体. class SonThread  imp ...

  2. 02_线程的创建和启动_继承Thread方式

    [简述] java使用Thread类代表线程,所有的线程都必须是Thread或者其子类的实例. 每个线程的任务就是完成一定的任务,实际上就是执行一段程序流. [创建并启动多线程的步骤(集成Thread ...

  3. Java线程:创建与启动

    Java线程:创建与启动 一.定义线程   1.扩展java.lang.Thread类.   此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 R ...

  4. Netty 学习(七):NioEventLoop 对应线程的创建和启动源码说明

    Netty 学习(七):NioEventLoop 对应线程的创建和启动源码说明 作者: Grey 原文地址: 博客园:Netty 学习(七):NioEventLoop 对应线程的创建和启动源码说明 C ...

  5. Java 线程的创建和启动

    Java 使用 Thread 类代表线程,所有的线程对象都必须是 Thread 类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码). Java 使用线程执 ...

  6. JAVA学习笔记16——线程的创建和启动

    Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码).Java使用线程执行体来代表这段 ...

  7. JavaSE---多线程---线程的创建、启动

    1.概述 1.1 Java中使用Thread类表示线程:   所有的线程对象必须是Thread类 或 其子类的实例:   每条线程的作用:完成一定的任务:   Java中使用run方法来封装线程执行体 ...

  8. Java基础-多线程-①线程的创建和启动

    简单阐释进程和线程 对于进程最直观的感受应该就是“windows任务管理器”中的进程管理: (计算机原理课上的记忆已经快要模糊了,简单理解一下):一个进程就是一个“执行中的程序”,是程序在计算机上的一 ...

  9. Java线程的创建及启动

    1.继承Thread类,重写该类的run()方法. package samTest; import java.util.Scanner; /** * Created by Sam on 2018-01 ...

随机推荐

  1. 【Stage3D学习笔记续】山寨Starling(一):从事件说起

    我在GitHub上新开了一个项目:https://github.com/hammerc/hammerc-study-Stage3D 山寨的Starling版本我取名叫做Scorpio2D,以后的笔记中 ...

  2. iOS7 人机界面设计指南

    iOS7 人机界面设计指南     苹果在WWDC 2013大会上发布了iOS 7,新系统一改5年来的拟物路线,在乔纳森•艾维的主导下,加入了更多的“扁平化”和“极简”现代设计元素. iOS7系统界面 ...

  3. hadoop 1.2 集群搭建与环境配置

    一.虚拟机环境 见我的另一篇博客http://www.cnblogs.com/xckk/p/6000881.html, 需要安装JDK环境,centos下安装JDK可参考: http://www.ce ...

  4. 用intent打开各种类型文件

    public class MyIntent { //android获取一个用于打开HTML文件的intent public static Intent getHtmlFileIntent( Strin ...

  5. Android studio插件安装

    Android Studio安装插件的方式其实和Eclipse大同小异.废话不多说,直接上图: 区域1:你当前已经安装了的插件 区域2:在线安装 区域3:从硬盘安装,即针对你已经下载好了的插件,可通过 ...

  6. Android设计模式系列--观察者模式

    观察者模式,是一种非常常见的设计模式,在很多系统中随处可见,尤其是涉及到数据状态发生变化需要通知的情况下.本文以AbstractCursor为例子,展开分析.观察者模式,Observer Patter ...

  7. 通过存储过程进行分页查询的SQL示例

    --创建人:zengfanlong --创建时间:-- :: --说明:根据公司简写代码获取当前待同步的气瓶档案数据(分页获取) ALTER PROCEDURE [UP_GasBottles_GetS ...

  8. android获取mac地址方法

    http://www.cnblogs.com/xioapingguo/p/4037513.html 网上找的,记录一下 public static String getMacAdress(){ Wif ...

  9. 期望-pku-oj-1055:Tree

    题目链接: http://poj.openjudge.cn/practice/1055/ 题目意思: 给出的树最大节点个数为n的情况下,求树上点深度的期望. 解题思路: 数学期望公式的推导. 自己先画 ...

  10. istringstream

    编写程序,将来自一个文件中的行保存在一个vector<string>中,然后使用一个istringstream从vector读取数据成员,每次读取一个单词 #include <ios ...