• Executor 框架


    Java的线程既是工作单元,也是执行机制。从JDK5开始,把工作单元与执行机制分离开来。工作单元包括RunnableCallable,而执行机制由Executor框架提供。

    Executor 框架简介

    HotSpot VM的线程模型中,Java线程被一对一映射为本地操作系统线程。Java线程启动时会创建一个本地操作系统线程;当该Java线程终止时,这个操作系统线程也被收回。操作系统会调度所有线程并将他们分配给可用的CPU。如图

    两级调度模型

    Executor 框架结构

    主要由3大部分组成:

    • 任务:包括被执行任务需要实现的接口:Runnable接口和Callable接口
    • 任务的执行:包括任务执行机制的核心接口Executor,以及继承自它的ExecutorService接口。有两个关键类实现了ExecutorService接口(ThreadPoolExecutorScheduledThreadPoolExecutor)。
    • 异步计算的结果:包括接口Future和实现它的FutureTask
    Executor框架的成员
    • ThreadPoolExecutor:通常使用工具类Executors来创建。Executors可以创建3种类型的ThreadPoolExecutor:
      • SingleThreadExecutor:用于需要保证顺序地执行每个任务,并且在任意时间点不会有多个线程是活动的应用场景。下面是创建单个线程的API
      public static ExecutorService newSingleThreadExecutor();
      public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)
      
      • FixedThreadPool:用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景,它适用于负载比较重的服务器。下面是创建使用固定线程数的FixedThreadPool的API
      public static ExecutorService newFixedThreadPool(int nThreads);
      public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);
      
      • CachedThreadPool:它是无界大小的线程池,用于执行很多短期异步小任务的小程序,或者是负载比较轻的服务器。下面是创建一个根据需要创建新线程的API
      public static ExecutorService newCachedThreadPool();
      public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);
      
    • ScheduledThreadPoolExecutor:通常使用工具类Executors来创建。Executors可以创建2种类型的ScheduledThreadPoolExecutor:
      • ScheduledThreadPoolExecutor:包含若干个线程的ScheduledThreadPoolExecutor,适用于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程的数量的场景。下面是创建的API:
      public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
      public static ScheduledExecutorService newScheduledThreadPool(
              int corePoolSize, ThreadFactory threadFactory);
      
      • SingleThreadScheduledExecutor:只包含一个线程的ScheduledThreadPoolExecutor,适用于需要单个线程执行周期任务,同时需要保证顺序地执行各个任务的场景。下面是创建的API:
      public static ScheduledExecutorService newSingleThreadScheduledExecutor();
      public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory);
      
    • Future接口
      Future接口和实现Future接口的FutureTask类用来表示异步计算的结果。当我们把Runnable接口或Callable接口的实现类提交(submit)给ThreadPoolExecutorScheduledThreadPoolExecutor时,ThreadPoolExecutorScheduledThreadPoolExecutor会向我们返回一个FutureTask对象。下面是对应API:
    public <T> Future<T> submit(Callable<T> task)
    public <T> Future<T> submit(Runnable task, T result)
    public Future<?> submit(Runnable task)
    
    • Runnable接口和Callable接口
      这两个接口的实现类都可以被ThreadPoolExecutorScheduledThreadPoolExecutor执行,最后一个方法没有返回值,其他均可以通过得到的FutureTask对象的get方法获取执行后结果。
    public class ExecutorTest {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            ExecutorService executor = Executors.newFixedThreadPool(5);
            //submit(Runnable task)
            Future<String> f1 = executor.submit(new Runnable(){
                @Override
                public void run() {
                    System.out.println(1);
                }
            },"result");
            System.out.println(f1.get());
            //submit(Runnable task,T result)
            Future f2 = executor.submit(new Runnable(){
                @Override
                public void run() {
                    System.out.println(2);
                }
            });
            System.out.println(f2.get());
            //submit(Callable<T> task)
            Future<String> f3 = executor.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println(3);
                    return "result";
                }
            });
            System.out.println(f3.get());
           
            executor.shutdown();
        }
    }
    

    执行结果

    1
    result
    2
    null
    3
    result
    

    除了自己实现Callable接口外,Executors可以把一个Runnable包装成一个Callable,下面是对应的API

    public static Callable<Object> callable(Runnable task)
    public static Callable<T> callable(Runnable task, T result)
    

    此时将这种转换过的对象交给ThreadPoolExecutorScheduledThreadPoolExecutor执行时,第一个种转换方法不会有返回值。

            Callable c1 = Executors.callable(new Runnable() {
                @Override
                public void run() {
                    System.out.println(4);
                }
            });
    
            Callable c2 = Executors.callable(new Runnable() {
                @Override
                public void run() {
                    System.out.println(5);
                }
            },"result2");
    
            Future f4 = executor.submit(c1);
            System.out.println(f4.get());
            Future f5 = executor.submit(c2);
            System.out.println(f5.get());
    

    执行结果

    4
    null
    5
    result2
    
  • 相关阅读:
    python redis操作
    subprocess模块的使用
    tcpcopy 流量复制工具
    Python名称空间与闭包
    python 偏函数
    Python面向对象的特点
    vsftpd 安装及使用虚拟用户配置
    shell 并发脚本
    Centos7 搭建LVS DR模式 + Keepalive + NFS
    python pip 升级
  • 原文地址:https://www.cnblogs.com/yuanmiemie/p/8566066.html
Copyright © 2020-2023  润新知