一、线程实现方式

  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. springboot oauth 鉴权之——授权码authorization_code鉴权

    近期一直在研究鉴权方面的各种案例,这几天有空,写一波总结及经验. 第一步:什么是 OAuth鉴权 OAuth2是工业标准的授权协议.OAuth2取代了在2006创建的原始OAuthTM协议所做的工作. ...

  2. mysql启动报错ERROR! The server quit without updating PID file处理

    从其它服务器拷贝编译安装后的MySQL5.7目录后启动时报错如下: ERROR! The server quit without updating PID file(/path/to/XXX.pid) ...

  3. CentOS7使用firewalld管理防火墙与端口

    firewalld的基本使用 启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status fir ...

  4. OpenStack官方镜像无法ssh登陆

    0x00 序 当前主流的Linux系统都有提供可以在OpenStack中直接使用cloud镜像,但当使用从官方网站下载的镜像创建云主机时,你会发现Linux下经常使用的ssh竟然无法登陆新创建好的云主 ...

  5. 悖论当道,模式成空:汽车O2O真是死得其所?

    O2O热潮的兴起似乎来得颇为蹊跷--或许是线上连接线下的模式太过空泛,具有极大的包容性,让各个行业都忍不住在其中横插一脚.在经历过最初的崛起和后来的火爆之后,最终形成目前的寒冬.究其原因,O2O并不是 ...

  6. 菜篮子成血战场!生鲜O2O为何厮杀如此惨烈

    衣食住行作为与大众生活直接挂钩的刚需,已经被诸多互联网企业全面渗入,并在彻底颠覆大众原有的生活形态.但其中作为最底层.最基本的"菜篮子"--生鲜市场,似乎仍然没有被互联网元素完全& ...

  7. linux lsof常用方法

    lsof简介 lsof(list open files)是一个列出当前系统打开文件的工具,在linux环境下,任何事物都是以文件形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.系统 ...

  8. 前端每日实战:114# 视频演示如何用纯 CSS 和混色模式创作一个 loader 动画

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/MqYroW 可交互视频 此视频是可 ...

  9. SVG 新手入门

    svg 入门新认知 一.第一步创建设置svg <svg width="100%" height="500"> </svg> 设置粗细 5 ...

  10. 使用CSS实现折叠面板总结

    任务目的 深入理解html中radio的特性 深入理解CSS选择器以及伪元素的使用 任务描述 使用input的radio单选框特性结合CSS中的伪元素实现bootstrap中折叠面板(点击查看样例), ...