zoukankan      html  css  js  c++  java
  • java 线程Thread 技术--1.5 Future与Callable

    Callable:

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

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

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

    一般我们是这么定义的:

    class Task implements Callable<Integer>{
    
        @Override
        public Integer call() throws Exception {
            
            return 900;
        }
        
    }

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

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

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

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

     public <T> Future<T> submit(Callable<T> task) {
            if (task == null) throw new NullPointerException();
            RunnableFuture<T> ftask = newTaskFor(task);           //-----------》 这里去new 了一个FutureTask(callable) ,并返回
            execute(ftask);                                 |
            return ftask;                                  |
        }                                            |
                                                   |
      protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {      |
            return new FutureTask<T>(callable);              《  ---------
        }

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

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

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

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

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

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

    package com.java.baseknowledge.concurrent15;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * 计算某一个区域里有多少个质数
     * @author iscys
     *
     */
    public class ThreadPool3 {
    
        
        public static void main(String[] args) throws Exception, ExecutionException {
            long start1 =System.currentTimeMillis();
            List<Integer> zhishu = getZhishu(0,20000);
            System.err.println(zhishu.size());
            System.err.println("单线程"+(System.currentTimeMillis()-start1));
            int thc = Runtime.getRuntime().availableProcessors();
            ExecutorService pool = Executors.newFixedThreadPool(thc*2);
            //lambda 表达式(param)->express
            Future<List<Integer>> ta1 = pool.submit(()->getZhishu(0,8000));
            //lambda 表达式(param)->{statement}
                Future<List<Integer>> ta2 = pool.submit(()->{
                System.out.println(Thread.currentThread().getName());
                List<Integer> ss = getZhishu(8001,13000);
                return ss;
                });
            Future<List<Integer>> ta3 = pool.submit(()->getZhishu(13001,17000));
            Future<List<Integer>> ta4 = pool.submit(()->{
    
            System.out.println(Thread.currentThread().getName());
    
            List<Integer> ss = getZhishu(17001,20000);
    
            return ss;
    
            });
    
            long start =System.currentTimeMillis();
            List<Integer> list = ta1.get();
            List<Integer> list2 = ta2.get();
            List<Integer> list3 = ta3.get();
            List<Integer> list4 = ta4.get();
            System.out.println(list.size()+list2.size()+list3.size()+list4.size());
            System.out.println(System.currentTimeMillis()-start);
            pool.shutdown();
        }
        
        static class MyTask implements Callable< List<Integer>>{
            int start ,end;
            MyTask(int start,int end){
                this.start=start;
                this.end=end;
            }
            @Override
            public List<Integer> call() throws Exception {
                // TODO Auto-generated method stub
                return getZhishu(start,end);
            }
            
        }
        
        
        
        
        
        static boolean isZhiShu(int num) {
            
            for(int i=2;i<=num/2;i++) {
                if(num%i==0) {return false;}
            }
            return true;
        }
        
        static List<Integer> getZhishu(int start,int end){
            
            List<Integer> li =new ArrayList<Integer>();
            
            for(int i=start;i<=end;i++) {
                if(isZhiShu(i)) {li.add(i);}
            }
            return li;
        }
    }
    原创打造,多多指教
  • 相关阅读:
    转载:从51CTO转来的两篇关于SQL的文章
    转载:几万年前,有一只猴子大闹地府后删库跑路...
    【java/oralce/sql】往一张仅有id,名称,创建时间三个字段的表中插入百万数据需要多久?1分26秒
    处处留心皆学问
    [oracle/java/sql]用于上十万批量数据插入Oracle表的Java程序
    Linux学习_003_虚拟机CentOS 7.5 如何固定IP地址
    Linux学习_002_VMware12.0 Pro 中安装 CentOS-7.5(桌面版)
    Linux学习_001_VMware10.0 && VMware12.0 Pro && VMware14.0 Pro && VMware 15.0 Pro 的安装与破解
    day76_淘淘商城项目_09_商品详情页动态展示实现(jsp+redis) + FreeMarker模板引擎入门 + 商品详情页静态化实现(Win版本的nginx作http服务器)_匠心笔记
    Eclipse注释模板设置详解
  • 原文地址:https://www.cnblogs.com/iscys/p/9721455.html
Copyright © 2011-2022 走看看