Callable:

从官方文档说起: 通过实现callable 的called 方法可以使一个任务可以返回一个结果以及可能抛出一个异常;

callable 与runnable 是相似的,可以被其他线程潜在的执行,但是runnable不会返回结果总是viod 以及不会抛出检测异常;

  1. /**
  2. * A task that returns a result and may throw an exception.
  3. * Implementors define a single method with no arguments called
  4. * {@code call}.
  5. *
  6. * <p>The {@code Callable} interface is similar to {@link
  7. * java.lang.Runnable}, in that both are designed for classes whose
  8. * instances are potentially executed by another thread. A
  9. * {@code Runnable}, however, does not return a result and cannot
  10. * throw a checked exception.
  11. *
  12. * <p>The {@link Executors} class contains utility methods to
  13. * convert from other common forms to {@code Callable} classes.

一般我们是这么定义的:

  1. class Task implements Callable<Integer>{
  2.  
  3. @Override
  4. public Integer call() throws Exception {
  5.  
  6. return ;
  7. }
  8.  
  9. }

但是我们如何能够获取到它的返回值?1.5 为我们提供了Future 接口,用于返回一个异步计算的结果,我们这样进行运行:

---线程池里去submit一个callable对象去执行;

  1. public static void main(String[] args) throws Exception, ExecutionException {
  2. ExecutorService pool = Executors.newFixedThreadPool(2);
  3.  
  4. //执行callale task,返回future 对象
  5. Future<Integer> submit = pool.submit(new Task());
  6. System.out.println(submit);
  7. Integer integer = submit.get();//obtain thread result ,is block
  8. System.out.println(integer);
  9. System.out.println(submit.isDone()) ;//is finish(trur or false)
  10.  
  11. }

我们追踪执行callable 的源码:发现内部使用了future实现类.        FutureTask 

  1. public <T> Future<T> submit(Callable<T> task) {
  2. if (task == null) throw new NullPointerException();
  3. RunnableFuture<T> ftask = newTaskFor(task); //-----------》 这里去new 了一个FutureTask(callable) ,并返回
  4. execute(ftask);                                 |
  5. return ftask;                                  |
  6. }                                            |
  7.                                                |
  8. protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {      |
  9. return new FutureTask<T>(callable);              《  ---------
  10. }

可以看到,其实在 executor 内部运行的是FutureTask ,FutureTask 实现了Future 以及runnable 接口,所以可以获得异步执行的结果;

因为实现了runnable 接口,所以可以这么执行

  1. public static void main(String[] args) throws InterruptedException, ExecutionException {
  2.  
  3. FutureTask<Integer> task =new FutureTask<>(new Task());
  4. new Thread(task).start();
  5. System.out.println(task.get());
  6. }

也可以直接使用executor 的execute方法:

  1. public static void main(String[] args) throws InterruptedException, ExecutionException {
  2. ExecutorService pool = Executors.newFixedThreadPool(2);
  3. FutureTask<Integer> task =new FutureTask<>(new Task());
  4. pool.execute(task);
  5. System.out.println(task.get());
  6.  
  7. }

接下来是一个小练习,比较单线程与多线程之间取1-20000之间的质数数量所花费的时间

  1. package com.java.baseknowledge.concurrent15;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.concurrent.Callable;
  6. import java.util.concurrent.ExecutionException;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. import java.util.concurrent.Future;
  10.  
  11. /**
  12. * 计算某一个区域里有多少个质数
  13. * @author iscys
  14. *
  15. */
  16. public class ThreadPool3 {
  17.  
  18. public static void main(String[] args) throws Exception, ExecutionException {
  19. long start1 =System.currentTimeMillis();
  20. List<Integer> zhishu = getZhishu(0,20000);
  21. System.err.println(zhishu.size());
  22. System.err.println("单线程"+(System.currentTimeMillis()-start1));
  23. int thc = Runtime.getRuntime().availableProcessors();
  24. ExecutorService pool = Executors.newFixedThreadPool(thc*2);
  25. //lambda 表达式(param)->express
  26. Future<List<Integer>> ta1 = pool.submit(()->getZhishu(0,8000));
  27. //lambda 表达式(param)->{statement}
  28. Future<List<Integer>> ta2 = pool.submit(()->{
  29. System.out.println(Thread.currentThread().getName());
  30. List<Integer> ss = getZhishu(8001,13000);
  31. return ss;
  32. });
  33. Future<List<Integer>> ta3 = pool.submit(()->getZhishu(13001,17000));
  34. Future<List<Integer>> ta4 = pool.submit(()->{
  35.  
  36. System.out.println(Thread.currentThread().getName());
  37.  
  38. List<Integer> ss = getZhishu(17001,20000);
  39.  
  40. return ss;
  41.  
  42. });
  43.  
  44. long start =System.currentTimeMillis();
  45. List<Integer> list = ta1.get();
  46. List<Integer> list2 = ta2.get();
  47. List<Integer> list3 = ta3.get();
  48. List<Integer> list4 = ta4.get();
  49. System.out.println(list.size()+list2.size()+list3.size()+list4.size());
  50. System.out.println(System.currentTimeMillis()-start);
  51. pool.shutdown();
  52. }
  53.  
  54. static class MyTask implements Callable< List<Integer>>{
  55. int start ,end;
  56. MyTask(int start,int end){
  57. this.start=start;
  58. this.end=end;
  59. }
  60. @Override
  61. public List<Integer> call() throws Exception {
  62. // TODO Auto-generated method stub
  63. return getZhishu(start,end);
  64. }
  65.  
  66. }
  67.  
  68. static boolean isZhiShu(int num) {
  69.  
  70. for(int i=2;i<=num/2;i++) {
  71. if(num%i==0) {return false;}
  72. }
  73. return true;
  74. }
  75.  
  76. static List<Integer> getZhishu(int start,int end){
  77.  
  78. List<Integer> li =new ArrayList<Integer>();
  79.  
  80. for(int i=start;i<=end;i++) {
  81. if(isZhiShu(i)) {li.add(i);}
  82. }
  83. return li;
  84. }
  85. }

java 线程Thread 技术--1.5 Future与Callable的更多相关文章

  1. java 线程Thread 技术--1.5 Executor Executors,ThreadPool,Queue

    Executors : Executors ,就是一个线程工具类:大部分操作线程的方法,都可以在这个工具类中就行创建,执行,调用一些线程的方法: Executor : 用于执行和提交一个runnabl ...

  2. java 线程Thread 技术--线程状态与同步问题

    线程技术第三篇: 线程的状态: 1. 创建状态: 当用new 操作符创建一个新的线程对象时,该线程就处于创建状态,系统不为它分配资源 2.可运行状态:当线程调用start 方法将为线程分配必须的系统资 ...

  3. java 线程Thread 技术--volatile关键字

    java 语言中允许线程访问共享变量,为了保证共享变量能被准确和一致的更新,Java 语言提供了volatile 关键字,也就是我们所说的内存一致性: 问题抛出:(尝试去运行下面代码,以及将volat ...

  4. java 线程Thread 技术--1.5Lock 与condition 演示生产者与消费模式

    在jdk 1.5 后,Java 引入了lock 锁来替代synchronized ,在使用中,lock锁的使用更加灵活,提供了灵活的 api ,不像传统的synchronized ,一旦进入synch ...

  5. java 线程Thread 技术--方法演示生产与消费模式

    利用wait 与notifyAll 方法进行演示生产与消费的模式的演示,我们两个线程负责生产,两个线程消费,只有生产了才能消费: 在effective Java 中有说过: 1. 在Java 中 ,使 ...

  6. java 线程Thread 技术--线程创建源码解释

    永远不要忘记最基础的东西,只有把最基础的知识打牢靠,才能够使你走的更远,我将从今天开始,进行线程知识的回顾,一些常用知识点,以及java1.5 引入的并发库,进行详细的讲解与总结 创建线程的目的是为了 ...

  7. java 线程Thread 技术--线程方法详解

    Thread 类常用的方法与Object类提供的线程操作方法:(一个对象只有一把锁

  8. java 线程Thread 技术--创建线程的方式

    在第一节中,对线程的创建我们通过看文档,得知线程的创建有两种方式进行实现,我们进行第一种方式的创建,通过继承Thread 类 ,并且重写它的run 方法,就可以进行线程的创建,所有的程序执行都放在了r ...

  9. java线程池技术(二): 核心ThreadPoolExecutor介绍

    版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...

随机推荐

  1. Oracle保留两位小数的函数

    1.最终保存成字符串类型 使用to_char()函数 // 其9代表:如果存在数字则显示数字,不存在则显示空格 // 其0代表:如果存在数字则显示数字,不存在则显示0,即占位符 // 其FM代表:删除 ...

  2. HTML Tags

    While some tags have a very specific purpose, such as image and video tags, most tags are used to de ...

  3. 6.5 Shell 算术计算

    6.5 Shell Arithmetic shell允许在其内计算表达式,可以通过以下方式使用:((中,let和带-i选项的declare命令中. 只能计算固定长度的整数,而且不会检查溢出,除0可以捕 ...

  4. 【381】python 获取列表中重复元素的索引值

    参考:获取python的list中含有重复值的index方法_python_脚本之家 核心思想:建立字典,遍历列表,把列表中每个元素和其索引添加到字典里面 cc = [1, 2, 3, 2, 4] f ...

  5. vue项目插入视频-mp4

    1. v.vue文件: <template> <div> <div class="contain"> <my-video :sources ...

  6. A*寻路初探(转载)

    启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标.这样可以省略大量无畏的搜索路径,提到了效率.在启发式搜索中,对位置的估价是十分重要 ...

  7. 新闻推荐系统:基于内容的推荐算法(Recommender System:Content-based Recommendation)

    https://blog.csdn.net/qq_32690999/article/details/77434381 因为开发了一个新闻推荐系统的模块,在推荐算法这一块涉及到了基于内容的推荐算法(Co ...

  8. Linux 创建用户 限制SFTP用户只能访问某个目录

    Linux 限制SFTP用户只能访问某个目录 1. 新建用户并设置密码 > useradd suser > passwd suser   // 输入密码 2. 设置sshd配置文件 > ...

  9. Error:svn: E160013 svn主干切换分支时报错

    Error:svn: E160013: û���ҵ��ļ�: �汾��10574����·�� ��/aap/branches/20180613�� 前几天遇到了这个问题,心里特别崩溃,之前可以从主干 ...

  10. 分享一个 Java String split 快速分割的方法

    java中string.split() 方法比较强大,但是split()方法采用正则表达式,速度相对会慢一点, 其实大多数场景下并不需要使用正则表达式,下面分享一个不使用正则表达式分隔字符串的方法. ...