zoukankan      html  css  js  c++  java
  • jdk线程池,使用手记

    Executors----------------------------------------------Executors----------------------------------------------Executors--------------

    为了更好的控制多线程,JDK提供了一套线程框架Executor,帮助开发人员有效的进行线程控制。它们都在java.util.concurrent包中,是JDK并发包的核心。
    其中有一个比较重要的类:Executors,他扮演着线程工厂的角色,我们通过Executors可以创建特定功能的线程池。
    Executors创建线程池方法:
      newFixedThreadPool();该方法返回一个固定数量的线程池,该方法的线程数始终不变,当有一个任务提交时,若线程池中空闲,则立即执行,若没有,
        则会被暂缓在一个任务队列中,等待有空闲的线程去执行。

      newSingleThreadExecutor();创建一个线程的线程池,若空闲则执行,若没有空闲线程则暂缓在任务队列中。
      newCachedThreadPool();返回一个可根据实际情况调整线程个数的线程池,不限制最大线程数量,若用空闲的线程则执行任务,若无任务则不创建线程。
        并且每一个空闲线程会在60秒后自动回收。
      newScheduledThreadPool();该方法返回一个SchededExecutorService对象,类似于第一个方法,但该线程池可以指定线程的数量。

    //创建出容量为10的线程池

    ExecutorService pool = Executors.newFixedThreadPool(10);
    //表示创建了容量为1的线程池
    ExecutorService pool2 = Executors.newSingleThreadExecutor();
    //创建容量没有限制的线程池
    ExecutorService pool3 = Executors.newCachedThreadPool();
    //创建固定数量的线程池(指定数量) 底层使用带有延迟和周期性的执行任务机制
    ScheduledExecutorService pool4 = Executors.newScheduledThreadPool(10);

    分析底层实现:
    newFixedThreadPool(10);
    /**
    * @param nThreads:核心线程
    * @return
    * new ThreadPoolExecutor
    * @param nThreads 核心线程(线程池被实例化后,其内部直接初始化了"nThreads"个线程)
    * @param nThreads 最大线程数
    * @param 0L 当前线程空闲时间为0
    * @param TimeUnit.MILLISECONDS 该线程空闲时间单位(秒、小时...)
    * @param new LinkedBlockingQueue<Runnable>() (一种无界队列类型)的存储器,如果池子没有空闲的话,新的线程将会被载入到该队列中
    */
    public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>());
    }

    newSingleThreadExecutor();
    /**
    * @return
    * new FinalizableDelegatedExecutorService
    * ThreadPoolExecutor
    * @param 1 默认在池子里创建一个线程
    * @param 1 池子默认大小为1
    * @param 0L 当前线程空闲时间为0
    * @param TimeUnit.MILLISECONDS 该线程空闲时间单位(秒、小时...)
    * @param new LinkedBlockingQueue<Runnable>() (一种无界队列类型)的存储器,如果池子没有空闲的话,新的线程将会被载入到该队列中
    */
    public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
    (new ThreadPoolExecutor(1, 1,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>()));
    }
    
    
    newCachedThreadPool();
    /**
    * @return
    * new ThreadPoolExecutor
    * @param 0 初始化该线程池的时候默认不创建线程
    * @param Integer.MAX_VALUE 默认该池子的大小为 MAX_VALUE (即不限制大小)
    * @param 0 初始化该线程池的时候默认不创建线程
    * @param TimeUnit.MILLISECONDS 该线程空闲时间单位(秒、小时...)
    * @param new SynchronousQueue<Runnable>())阻塞队列,用于存储等待的任务

    */
    public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
    60L, TimeUnit.SECONDS,
    new SynchronousQueue<Runnable>());
    }


    Executors----------------------------------------------Executors----------------------------------------------Executors--------------
    
    
    同步辅助类----------------------------------------------同步辅助类----------------------------------------------同步辅助类--------------
    CountDownLatch  在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待; 
    使用场景:常用语监听某些初始化操作,等初始化执行完毕后,通知主线程继续工作。

      构造方法参数指定了计数的次数

      countDown方法,当前线程调用此方法,则计数减一

      await方法,调用此方法会一直阻塞当前线程,直到计时器的值为0

     1 public class CountDownLatchDemo {
     2     final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     3     public static void main(String[] args) throws InterruptedException {
     4         CountDownLatch latch=new CountDownLatch(2);//两个工人的协作
     5         Worker worker1=new Worker("zhang san", 5000, latch);
     6         Worker worker2=new Worker("li si", 8000, latch);
     7         worker1.start();//
     8         worker2.start();//
     9         latch.await();//等待所有工人完成工作
    10         System.out.println("all work done at "+sdf.format(new Date()));
    11     }
    12     
    13     
    14     static class Worker extends Thread{
    15         String workerName; 
    16         int workTime;
    17         CountDownLatch latch;
    18         public Worker(String workerName ,int workTime ,CountDownLatch latch){
    19              this.workerName=workerName;
    20              this.workTime=workTime;
    21              this.latch=latch;
    22         }
    23         public void run(){
    24             System.out.println("Worker "+workerName+" do work begin at "+sdf.format(new Date()));
    25             doWork();//工作了
    26             System.out.println("Worker "+workerName+" do work complete at "+sdf.format(new Date()));
    27             latch.countDown();//工人完成工作,计数器减一
    28 
    29         }
    30         
    31         private void doWork(){
    32             try {
    33                 Thread.sleep(workTime);
    34             } catch (InterruptedException e) {
    35                 e.printStackTrace();
    36             }
    37         }
    38     }
    39     
    40      
    41 }

    输出:

    Worker zhang san do work begin at 2011-04-14 11:05:11
    Worker li si do work begin at 2011-04-14 11:05:11
    Worker zhang san do work complete at 2011-04-14 11:05:16
    Worker li si do work complete at 2011-04-14 11:05:19
    all work done at 2011-04-14 11:05:19

    
    
    CyclicBarrier 它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,
      这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
    使用场景:需要所有的子任务都完成时,才执行主任务,这个时候就可以选择使用CyclicBarrier。
    method:
    await
    public int await()
              throws InterruptedException,
                     BrokenBarrierException
    在所有参与者都已经在此 barrier 上调用 await方法之前,将一直等待。如果当前线程不是将到达的最后一个线程,出于调度目的,将禁用它,且在发生以下情况之一前,该线程将一直处于休眠状态:
    最后一个线程到达;或者
    其他某个线程中断当前线程;或者
    其他某个线程中断另一个等待线程;或者
    其他某个线程在等待 barrier 时超时;或者
    其他某个线程在此 barrier 上调用 reset()。
    如果当前线程:
    在进入此方法时已经设置了该线程的中断状态;或者
    在等待时被中断
    则抛出 InterruptedException,并且清除当前线程的已中断状态。如果在线程处于等待状态时 barrier 被 reset(),或者在调用 await 时 barrier 被损坏,抑或任意一个线程正处于等待状态,
    则抛出 BrokenBarrierException 异常。 如果任何线程在等待时被 中断,则其他所有等待线程都将抛出 BrokenBarrierException 异常,并将 barrier 置于损坏状态。 如果当前线程是最后一个将要到达的线程,并且构造方法中提供了一个非空的屏障操作,则在允许其他线程继续运行之前,当前线程将运行该操作。如果在执行屏障操作过程中发生异常,
    则该异常将传播到当前线程中,并将 barrier 置于损坏状态。 返回: 到达的当前线程的索引,其中,索引 getParties() - 1 指示将到达的第一个线程,零指示最后一个到达的线程 抛出: InterruptedException - 如果当前线程在等待时被中断 BrokenBarrierException - 如果另一个 线程在当前线程等待时被中断或超时,或者重置了 barrier,或者在调用 await 时 barrier 被损坏,抑或由于异常而导致屏障操作(如果存在)失败。
    
    

      

    
    
     1 public class CyclicBarrierTest {  
     2   
     3     public static void main(String[] args) throws IOException, InterruptedException {  
     4         //如果将参数改为4,但是下面只加入了3个选手,这永远等待下去  
     5         //Waits until all parties have invoked await on this barrier.   
     6         CyclicBarrier barrier = new CyclicBarrier(3);  
     7   
     8         ExecutorService executor = Executors.newFixedThreadPool(3);  
     9         executor.submit(new Thread(new Runner(barrier, "1号选手")));  
    10         executor.submit(new Thread(new Runner(barrier, "2号选手")));  
    11         executor.submit(new Thread(new Runner(barrier, "3号选手")));  
    12   
    13         executor.shutdown();  
    14     }  
    15 }  
    16   
    17 class Runner implements Runnable {  
    18     // 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)  
    19     private CyclicBarrier barrier;  
    20   
    21     private String name;  
    22   
    23     public Runner(CyclicBarrier barrier, String name) {  
    24         super();  
    25         this.barrier = barrier;  
    26         this.name = name;  
    27     }  
    28   
    29     @Override  
    30     public void run() {  
    31         try {  
    32             Thread.sleep(1000 * (new Random()).nextInt(8));  
    33             System.out.println(name + " 准备好了...");  
    34             // barrier的await方法,在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。  
    35             barrier.await();  
    36         } catch (InterruptedException e) {  
    37             e.printStackTrace();  
    38         } catch (BrokenBarrierException e) {  
    39             e.printStackTrace();  
    40         }  
    41         System.out.println(name + " 起跑!");  
    42     }  
    43 }  

    输出:

    3号选手 准备好了...
    2号选手 准备好了...
    1号选手 准备好了...
    1号选手 起跑!
    2号选手 起跑!
    3号选手 起跑!






    同步辅助类----------------------------------------------同步辅助类----------------------------------------------同步辅助类--------------
  • 相关阅读:
    在C#程序设计中使用Win32类库
    Quartz.Net学习笔记(一)
    XDView网络视频监控
    Quartz.Net学习笔记(二) Jobs And Triggers
    关于web.config中<customErrors>节点说明
    业余水准,给朋友设计的LOGO
    JS 获取浏览器、显示器 窗体等宽度和高度【转载】
    Quartz.Net学习笔记(三) Jobs And Triggers再深入
    自己asp.net项目错误处理机制
    asp.net错误处理机制
  • 原文地址:https://www.cnblogs.com/john69-/p/6840915.html
Copyright © 2011-2022 走看看