一、线程实现方式

  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. 为何印度打车软件Ola,也难逃“资本合并”命运?

    从全球市场来看,共享经济已经引发了多场具有颠覆性的风暴.尤其是在与大众关系紧密的衣食住行方面,诞生了具有强势影响力的独角兽企业.如,共享打车企业Uber.共享房屋出租企业Airbnb等.而鉴于每个国家 ...

  2. js 原生轮播图插件

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. java连接sqlserver数据简单操作

    首先我们下载微软的JDBC驱动包 https://www.microsoft.com/en-us/download/details.aspx?id=11774 下载好后我们打开如下图 点击Unzip ...

  4. 在python中使用json

    在服务器和客户端的数据交互的时候,要找到一种数据格式,服务端好处理,客户端也好处理,这种数据格式应该是一种统一的标准,不管在哪里端处理起来都是统一的,现在这种数据格式非常的多,比如最早的xml,再后来 ...

  5. Python Mock 的入门

    Mock是什么 Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是模拟一些东西.准确的说,Mock是Python中一个用于支持单元测试的库,它的主要功能是使用mock对象替代 ...

  6. Spring Boot 学习1-创建Spring Boot应用

    如果使用Maven, 确保先安装好Maven再继续. 创建POM文件 在这里有两种方式: 继承Spring Boot parent的pom. 不继承. 继承Spring Boot pom 1 2 3 ...

  7. C2C的道德边界:沦为从假运单到假病条的供假渠道

    你可能刚开始学会不去看网购平台上商品回评中的虚假好评,却又要开始应对同事在朋友圈等平台买来的虚开病假条带来的困扰.最近各大媒体包括党报热传的网购病假条事件,再度将人们的目光集中在这个C2C模式之上.从 ...

  8. 冒泡排序算法(C#、Java、Python、JavaScript、C、C++实现)

    一.介绍 它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小.首字母从Z到A)错误就把他们交换过来. 走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排 ...

  9. poi简介

    POI简介(用于操作Excel) 1 Java Aspose Cells Java Aspose Cells 是一种纯粹的Java授权的Excel API,开发和供应商Aspose发布.这个API的最 ...

  10. 7-2 jmu-python-九九乘法表(矩形) (10 分)

    本题目要求输出如下图所示的九九乘法表 注:乘积要求做格式控制,占4个位置的宽度 输入样例: 无 输出样例: 1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8= ...