04_线程的创建和启动_使用Callable和Future的方式
【简述】
从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的方式的更多相关文章
- 03_线程的创建和启动_实现Runnable接口方式
[线程的创建和启动的步骤(实现Runnable接口方式)] 1.定义Runnable接口的实现类,并重写其中的run方法.run()方法的方法体是线程执行体. class SonThread imp ...
- 02_线程的创建和启动_继承Thread方式
[简述] java使用Thread类代表线程,所有的线程都必须是Thread或者其子类的实例. 每个线程的任务就是完成一定的任务,实际上就是执行一段程序流. [创建并启动多线程的步骤(集成Thread ...
- Java线程:创建与启动
Java线程:创建与启动 一.定义线程 1.扩展java.lang.Thread类. 此类中有个run()方法,应该注意其用法: public void run() 如果该线程是使用独立的 R ...
- Netty 学习(七):NioEventLoop 对应线程的创建和启动源码说明
Netty 学习(七):NioEventLoop 对应线程的创建和启动源码说明 作者: Grey 原文地址: 博客园:Netty 学习(七):NioEventLoop 对应线程的创建和启动源码说明 C ...
- Java 线程的创建和启动
Java 使用 Thread 类代表线程,所有的线程对象都必须是 Thread 类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码). Java 使用线程执 ...
- JAVA学习笔记16——线程的创建和启动
Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码).Java使用线程执行体来代表这段 ...
- JavaSE---多线程---线程的创建、启动
1.概述 1.1 Java中使用Thread类表示线程: 所有的线程对象必须是Thread类 或 其子类的实例: 每条线程的作用:完成一定的任务: Java中使用run方法来封装线程执行体 ...
- Java基础-多线程-①线程的创建和启动
简单阐释进程和线程 对于进程最直观的感受应该就是“windows任务管理器”中的进程管理: (计算机原理课上的记忆已经快要模糊了,简单理解一下):一个进程就是一个“执行中的程序”,是程序在计算机上的一 ...
- Java线程的创建及启动
1.继承Thread类,重写该类的run()方法. package samTest; import java.util.Scanner; /** * Created by Sam on 2018-01 ...
随机推荐
- Stage3D学习笔记(一):3D术语简介
网格(Mesh) 3D中,所有可见的模型都被称作网格.网格是由3DMax等建模软件制作,定义了一个3D物体的形状.一个网格是由多个多边形组成的. 多边形(Polygon) 一个多边形是组成网格的一个最 ...
- mac磁盘满解决方案
背景 : 用mac电脑的人,估计都不习惯去关机吧.mac虽然可以不需要关闭电脑,但是久而久之由于应用软件占用产生缓存文件 or 产生虚拟内容交换文件 or 睡眠镜像文件 and so on. 会占用大 ...
- Android设计模式系列--模板方法模式
模板方法,和单例模式是我认为GOF的23中最简单的两种模式.但是我个人对模板方法的经典思想特别推崇,虽然模板方法在大对数情况下并不被推荐使用,但是这种通过父类调用子类的方法,使用继承来改变算法的一部分 ...
- Spring3 MVC Login Interceptor(Spring 拦截器)
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- iOS开发——面试笔试精华(一)
面试笔试精华(一) 1. #import 跟#include.@class有什么区别?#import<> 跟 #import”"又什么区别? 1> #imp ...
- WSGI、flup、fastcgi、web.py的关系
Apache/lighttpd: 相当于一个request proxy,根据配置,把不同的请求转发给不同的server处理,例如静态的文件请求自己处理,这个时候它就像一个web server,对于fa ...
- PAT 1012
1012. The Best Rank (25) To evaluate the performance of our first year CS majored students, we consi ...
- 项目源码--Android高质量图片浏览器源码
下载源码 技术要点: 1. 浏览所有格式的图片 2. 图片缓存到数据库 3. Sqlite数据库的高级应用 4. 文件夹缩图显示 5. 多点触控技术 6. 动画技术 7. 支持超高清图片 8. ...
- AsyncTask的用法
在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行.在单线程模型中始终要记住两条法则: 1. 不要阻塞UI线程 2. 确保只 ...
- 父元素onmouseover触发事件在父子元素间移动不停触发的问题
今天写了一个侧边栏动态展开收缩的效果 <!DOCTYPE html> <html lang="en"> <head> <meta char ...