【简述】

从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. 剑指OFFER之第一个只出现一次的字符(九度OJ1283)

    题目描述: 在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符. 输入: 输入有多组数据每一组输入一个字符串. 输出: 输出第一个只出现一次的字 ...

  2. iOS动画详解(二)

    UIImage常用的绘图操作   一个UIImage对象提供了向当前上下文绘制自身的方法.我们现在已经知道如何获取一个图片类型的上下文并将它转变成当前上下文.   平移操作:下面的代码展示了如何将UI ...

  3. Android 上拉加载更多功能

    前几天看了github上面的例子,参照它的实现,自己又稍微改了一点,往项目里面增加了一个上拉加载更多功能.具体的实现如下: 首先要重写ListView: import android.content. ...

  4. java中调用dll文件的两种方法

    一中是用JNA方法,另外是用JNative方法,两种都是转载来的, JNA地址:http://blog.csdn.net/shendl/article/details/3589676   JNativ ...

  5. <转>linux 下stm32开发环境安装

    传送门: http://www.eefocus.com/marianna/blog/13-10/298454_7e04f.html http://blog.sina.com.cn/s/blog_643 ...

  6. ios常用动画

    // // CoreAnimationEffect.h // CoreAnimationEffect // // Created by VincentXue on 13-1-19. // Copyri ...

  7. 修改LiteIDE 编辑窗口的主题

    用习惯了Visual Studio 再看其他编译器总是有点别扭,当然LiteIDE 也是能够自定义主题的,再次感叹作者的用心. 依次: 查看 -> 选项 -> LiteEditor 在编辑 ...

  8. 获取设置dom属性

    getAttribute():获取dom节点属性,带一个参数,表示要获取的属性使用方法:object.getAttribute("id"); setAttribute():设置do ...

  9. JVMInternals--reference

    This article explains the internal architecture of the Java Virtual Machine (JVM). The following dia ...

  10. 使用RecyclerView实现瀑布流的效果

    主函数: public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; privat ...