一、线程实现方式

  1.继承Thread类

  2.实现Runnable接口

  3.线程池

  4.Callable

二、无论使用继承Thread类还是实现Runnable接口,还是使用线程池都没有办法解决2个问题

  1.线程执行没有返回值结果

  2.线程执行没有办法抛出异常,只能自己通过try-catch解决

三、Callable

  在java中,创建线程一般有两种方式,一种是继承Thread类,一种是实现Runnable接口。然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果。我们一般只能采用共享变量或共享存储以及线程通信的方式实现获得任务结果的目的;  

  不过,在java中,也提供了使用Callable和Future来实现获取任务结果的操作。Callable用来执行任务,产生结果,而Future用来获得结果;

@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}

四、Callable和Runnable的区别

  1、Callable能接受一个泛型,然后在call方法中返回一个这个类型的值,而Runnable的run方法没有返回值;

  2、Callable的call方法可以抛出异常,而Runnable的run方法不会抛出异常;

五、Future

  Future莫斯的核心在于:去除了函数的等待时间,并使得原来需要等待的时间段可以用于处理其他业务逻辑;

  Future模式:对于多线程,如果线程A要等待线程B的结果,那么线程A没有必要等待线程B,知道线程B有结果,可以先拿到一个未来的Future,等线程B有结果时再取真实的结果;

1、调用Callable的第一种实现方案

package com.zn.callableTest;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Callable接口中重写的Call方法,可以有返回值并且抛出异常");
return "callable";
} //调用Callable的第一种实现方案
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable=new MyCallable();
//利用FutureTask执行Callable并且接受结果
FutureTask<String> stringFutureTask = new FutureTask<>(myCallable);
//利用线程执行Task任务
new Thread(stringFutureTask).start();
//接受结果FutureTask.get会发生阻塞情况
System.out.println(stringFutureTask.get()); System.out.println("MyCallable执行完毕,返回值结果正确接收~");
}
}

控制台效果:

   

2、调用Callable的第二种实现方案

package com.zn.callableTest;

import java.util.concurrent.*;

public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Callable接口中重写的Call方法,可以有返回值并且抛出异常");
return "callable";
} //调用Callable的第二种实现方案
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
MyCallable myCallable=new MyCallable();
//创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
//创建线程执行任务,接受任务结果
Future<String> future = executorService.submit(myCallable);
//接受返回值
System.out.println(future.get(2000,TimeUnit.MILLISECONDS));
System.out.println("方式二,线程池:MyCallable执行完毕,返回值结果正确接收~");
//停止线程池
executorService.shutdown();
}
}

控制台效果:

  

六、Future常用方法

  V get():获取异步执行的结果,如果没有结果可用,此方法会阻塞知道异步计算完成;

  V get(Long timeout,TimeUnit unit):获取异步执行结果,如果没哟结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常;

  boolean isDone():如果任务执行结束,无论是正常结束或是中途取消还是发生异常,都返回true;

  boolean isCanceller():如果任务完成前被取消,则返回true;

  boolean cancel(boolean mayInterrupRunning):如果任务还没有开始,执行cancel方法将返回false;如果任务已经启动,执行cancel方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回true;

  当任务已经启动,执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回false;

  当任务已经启动,执行cancel方法将返回false,MayInterruptRunning参数表示是否中断执行中的线程;

实际上Future提供了三种功能:

  • 能够中断执行中的任务;
  • 判断任务是否执行完成;
  • 获取任务执行完成后的结果;

七、Future提供三种功能

1.中断任务cancel(true)

package com.zn.callableTest;

import java.util.concurrent.*;

public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Callable接口中重写的Call方法,可以有返回值并且抛出异常");
return "callable";
} public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
MyCallable myCallable=new MyCallable();
//创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
//创建线程执行任务,接受任务结果
Future<String> future = executorService.submit(myCallable);
//中断任务
boolean cancel = future.cancel(true);
if(cancel){
System.out.println("中断任务成功~");
}else{
//接受返回值
System.out.println(future.get(2000,TimeUnit.MILLISECONDS)); } //停止线程池
executorService.shutdown();
}
}

控制台效果:

  

2.判断任务是否执行完成isDone()

3.获取任务执行后的结果get()

八、手写Future模式

package com.zn.callableTest;

/**
* 手写Future模式
*/
public class MyFuture {
//FLAG相当于数据标识,如果放入数据成功,则返回为true,否则返回为false
private static boolean FLAG=false;
private String data; public synchronized void setData(String data) throws InterruptedException {
Thread.sleep(2000);
//赋值操作
this.data = data;
FLAG=true;
//唤起
notify();
} public synchronized String getData() {
//如果获取数据失败
if(!FLAG){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return data;
} public static void main(String[] args) {
MyFuture future=new MyFuture();
new Thread(()->{
try {
future.setData("张三");
System.out.println(future.getData());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}

控制台效果:

  

Callable的Future模式的更多相关文章

  1. java:并发编程-Callable与Future模式

    自己对线程池的理解: coresize 3 maxsize 5 blockLinkedQuenue 3 当提交的任务在<=3时,创建三个线程干活 大于3时,把任务先加入阻塞式队列,当有空闲的核心 ...

  2. 并发编程之Callable异步,Future模式

    Callable 在Java中,创建线程一般有两种方式,一种是继承Thread类,一种是实现Runnable接口.然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果.我们一般只能采用共享变 ...

  3. Java线程池(Callable+Future模式)

    转: Java线程池(Callable+Future模式) Java线程池(Callable+Future模式) Java通过Executors提供四种线程池 1)newCachedThreadPoo ...

  4. 线程笔记:Future模式

    线程技术可以让我们的程序同时做多件事情,线程的工作模式有很多,常见的一种模式就是处理网站的并发,今天我来说说线程另一种很常见的模式,这个模式和前端里的ajax类似:浏览器一个主线程执行javascri ...

  5. Java线程(七):Callable和Future

    转自:http://blog.csdn.net/ghsau/article/details/7451464 本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果. C ...

  6. 并发编程 05—— Callable和Future

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  7. Java并发(8):CountDownLatch、CyclicBarrier、Semaphore、Callable、Future

    CountDownLatch.CyclicBarrier.Semaphore.Callable.Future  都位于java.util.concurrent包下,其中CountDownLatch.C ...

  8. Future模式

    Future模式简介 Future模式有点类似于网上购物,在你购买商品,订单生效之后,你可以去做自己的事情,等待商家通过快递给你送货上门.Future模式就是,当某一程序提交请求,期望得到一个答复.但 ...

  9. 【Java线程】Callable和Future

    Future模式 Future接口是Java线程Future模式的实现,可以来进行异步计算. Future模式可以这样来描述: 我有一个任务,提交给了Future,Future替我完成这个任务.期间我 ...

随机推荐

  1. 吴裕雄--天生自然KITTEN编程:拾金币

  2. 吴裕雄--天生自然 R语言数据分析:火箭发射的地点、日期/时间和结果分析

    dfS = read.csv("F:\\kaggleDataSet\\spacex-missions\\database.csv") library(dplyr) library( ...

  3. 吴裕雄--天生自然 PYTHON数据分析:医疗数据分析

    import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.rea ...

  4. centos7添加阿里云的epel源

    有些包在别的yum源找不到,在阿里云的yum源里成功找到,这里记录在不影响base源的情况快速添加epel源的添加方法 wget https://mirrors.aliyun.com/epel/7Se ...

  5. 使用itchat发送天气信息

    微信发送当日天气情况 念头萌生 之前在浏览网站的时候发现了篇文章「玩转树莓派」为女朋友打造一款智能语音闹钟,文章中介绍了使用树莓派打造一款语音播报天气的闹钟. 当时就想照着来,也自己做个闹钟.因为一直 ...

  6. ES插件升级

    #!/bin/bash mkdir -p /home/esuser cd /home/esuser wget http://10.12.xx.xx:8090/search_plugins/sd_wai ...

  7. Mybatis: 插件及分页

    Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的). Mybatis支持对Executor.StatementHa ...

  8. 在使用vue+webpack模版创建的项目中使用font-awesome

    前言:最近使用vue+webpack进行一个小项目的开发,按照官方模版文档完成项目初始化后打算引入ont-awesome字体图标库进行使用,引入过程中遇到一些问题并解决,现记录如下. 一开始进展很顺利 ...

  9. diary20180428

    17:05:59 今天早晨去了图书馆.学习了一把vscode.试图在河边看电脑,总有小虫不让我专心. 23:27:34 看纯黑直播打战神,有点感触. 动漫或游戏,角色觉醒,实力大增,小时候(甚至现在) ...

  10. FPGA小白学习之路(4)PLL中的locked信号解析(转)

    ALTPLL中的areset,locked的使用 转自:http://www.360doc.com/content/13/0509/20/9072830_284220258.shtml 今天对PLL中 ...