• JDK并发包二


    JDK并发包二

    线程复用——线程池

    在线程池中,总有那么几个活跃的线程,当程序需要线程时可以从池子中随便拿一个控线程,当程序执行完毕,线程不关闭,而是将这个线程退会到池子,等待使用。

    JDK提供了一套Executor框架,可以有效进行线程控制。ThreadPoolExecutor表示一个线程池,Executors类相当与线程池工厂,通过Executors可以获得一个拥有特定功能的线程池。

    Executors框架提供了各类线程池,主要有下面工厂方法

    public static ExecutorService newFixedThreadPool(int nThreads);
    public static ExecutorService newSingleThreadExecutor() ;
    public static ExecutorService newCachedThreadPool();
    public static ScheduledExecutorService newSingleThreadScheduledExecutor();
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);

    • newFixedThreadPool()此方法返回一个有固定线程数量的线程池。当一个新的任务提交时,线程中若有空闲线程则立即执行,若无则会暂存在一个任务队列中,待有线程空闲时,再进行处理。
    • newSingleThreadExecutor()此方法返回一个只有一个线程的线程池,有新任务提交到线程池中会被安排到任务队列中,等待执行。
    • newCachedThreadPool()此方法返回一个根据实际情况调整线程数量的线程池,线程池中线程的数量不确定,若有新任务,线程池中有空闲线程,就复用空闲线程,如果没有就重新开启一个新的线程执行。
    • newSingleThreadScheduledExecutor()此方法返回一个ScheduledExecutorService对象,线程池大小为1,ScheduledExecutorService可以周期执行某个任务
    • newScheduledThreadPool() 此方法返回一个ScheduledExecutorService对象 但可以指定线程数量。
    1. 固定任务
    public static void main(String[] args) {
    
            MyTesk myTesk = new MyTesk();
            ExecutorService executorService = Executors.newFixedThreadPool(5);
            for (int i = 0; i < 10; i++) {
                executorService.submit(myTesk);
            }
            executorService.shutdown();
        }
    
    
        static class MyTesk implements Runnable {
    
            @Override
            public void run() {
    
                System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "线程执行");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    

    1. 计划任务

      ScheduledExecutorService有三个重要的方法来执行计划任务

    schedule(Runnable command,long delay, TimeUnit unit) ;

    scheduleAtFixedRate(Runnable command,
    long initialDelay,
    long period,
    TimeUnit unit);

    scheduleWithFixedDelay(Runnable command,
    long initialDelay,
    long delay,
    TimeUnit unit);

    schedule()会在设定的延时后执行一次。

    scheduleAtFixedRate()会在设定的延时(initialDelay)之后按照(period)为周期进行执行。若在下一个周期开始时当前任务未完成,则不会执行直到当前任务完成。若当前任务时间超出任务周期,则每次任务执行完就会立刻执行下一个任务。

    scheduleWithFixedDelay()会在设定的延时(initialDelay)之后执行任务,任务完成后间隔(delay)进行下一次执行

    如果有任务抛出异常则所有任务会全部停止执行

    核心线程池内部实现

     public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
    
        public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
     public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
        }
    

    ThreadPoolExecutor的构造方法

       public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler) 
    
    • corePoolSize 指定了线程池中线程的数量
    • maximumPoolSize 指定了线程池中最大线程数量
    • keepAliveTime 当线程池中线程数量超过corePoolSize后多余线程的存活时间
    • unit keepAliveTime的时间单位
    • workQueue 任务队列被提交,但未被执行的任务的任务
    • threadFactory 线程工厂,默认即可
    • handler 拒绝策略

    workQueue 任务队列

    • 直接提交队列

      由SynchronousQueue对象提供,SynchronousQueue没有容量 每一个插入操作都要等待一个删除操作,每一个删除都要等待对应的插入操作。使用SynchronousQueue提交的任务不会被真实保存,而是将新任务提交给线程执行,如果没有空闲线程就会试图创建新线程。如果进程数量已到达最大值,则执行拒绝策略。

    • 有界任务队列

      使用ArrayBlockingQueue实现,ArrayBlockingQueue(int capacity)capacity表示队列最大容量创建时必须给定当有新任务时,如果有空闲线程,就立即执行。没有则入队等待空闲线程,如果队列已满则尝试创建线程。如果线程数超过maximumPoolSize就会执行拒绝策略

    • 无界任务队列

      LinkedBlockingQueue类来实现 与有界相比,不同点在于队列不会满,只要内存资源足够可以一直添加到队列中,直到系统内存耗尽

    • 有限任务队列

      PriorityBlockingQueue可实现,它是一个特殊的无界队列,PriorityBlockingQueue可以根据任务的优先级顺序先后执行

    总之线程调用逻辑

  • 相关阅读:
    【转载】uboot的工具mkimage使用方法
    u-boot-2010.3移植到Tiny6410问题总结
    【转载】 GNU GCC 选项说明
    【转载】GCC 预处理器选项
    用kermit通过串口往nandflash任意地址里烧写任何文件!
    自己写Tiny6410的Bootloader总结!
    ARM常用汇编指令介绍
    Ubuntu14.04和Tiny6410挂载NFS服务!
    Tiny 6410的Linux学习总结!
    Tiny6410下的第一个Linux驱动程序
  • 原文地址:https://www.cnblogs.com/huangshen/p/13265505.html
Copyright © 2020-2023  润新知