zoukankan      html  css  js  c++  java
  • Java Executors(线程池)

    Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利。为了编写高效稳定可靠的多线程程序,线程部分的新增内容显得尤为重要。

      有关Java5线程新特征的内容全部在java.util.concurrent下面,里面包含数目众多的接口和类,熟悉这部分API特征是一项艰难的学习过程。目前有关这方面的资料和书籍都少之又少,大所属介绍线程方面书籍还停留在java5之前的知识层面上。

      当然新特征对做多线程程序没有必须的关系,在java5之前通用可以写出很优秀的多线程程序。只是代价不一样而已。

      线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。

      在Java5之前,要实现一个线程池是相当有难度的,现在Java5为我们做好了一切,我们只需要按照提供的API来使用,即可享受线程池带来的极大便利。

      Java5的线程池分好多种:具体的可以分为两类,固定尺寸的线程池、可变尺寸连接池。

      在使用线程池之前,必须知道如何去创建一个线程池,在Java5中,需要了解的是java.util.concurrent.Executors类的API,这个类提供大量创建连接池的静态方法,是必须掌握的。

    一、固定大小的线程池,newFixedThreadPool:

    1. package app.executors;  
    2.   
    3. import java.util.concurrent.Executors;  
    4. import java.util.concurrent.ExecutorService;  
    5.   
    6. /** 
    7.  * Java线程:线程池 
    8.  *  
    9.  * @author 冯小卫 
    10.  */  
    11. public class Test {  
    12.     public static void main(String[] args) {  
    13.         // 创建一个可重用固定线程数的线程池  
    14.         ExecutorService pool = Executors.newFixedThreadPool(5);  
    15.         // 创建线程  
    16.         Thread t1 = new MyThread();  
    17.         Thread t2 = new MyThread();  
    18.         Thread t3 = new MyThread();  
    19.         Thread t4 = new MyThread();  
    20.         Thread t5 = new MyThread();  
    21.         // 将线程放入池中进行执行  
    22.         pool.execute(t1);  
    23.         pool.execute(t2);  
    24.         pool.execute(t3);  
    25.         pool.execute(t4);  
    26.         pool.execute(t5);  
    27.         // 关闭线程池  
    28.         pool.shutdown();  
    29.     }  
    30. }  
    31.   
    32. class MyThread extends Thread {  
    33.     @Override  
    34.     public void run() {  
    35.         System.out.println(Thread.currentThread().getName() + "正在执行。。。");  
    36.     }  
    37. }  


    输出结果:

    1. pool-1-thread-1正在执行。。。  
    2. pool-1-thread-3正在执行。。。  
    3. pool-1-thread-4正在执行。。。  
    4. pool-1-thread-2正在执行。。。  
    5. pool-1-thread-5正在执行。。。  


    改变ExecutorService pool = Executors.newFixedThreadPool(5)中的参数:ExecutorService pool = Executors.newFixedThreadPool(2),输出结果是:

    1. pool-1-thread-1正在执行。。。  
    2. pool-1-thread-1正在执行。。。  
    3. pool-1-thread-2正在执行。。。  
    4. pool-1-thread-1正在执行。。。  
    5. pool-1-thread-2正在执行。。。  


    从以上结果可以看出,newFixedThreadPool的参数指定了可以运行的线程的最大数目,超过这个数目的线程加进去以后,不会运行。其次,加入线程池的线程属于托管状态,线程的运行不受加入顺序的影响。

    二、单任务线程池,newSingleThreadExecutor:

    仅仅是把上述代码中的ExecutorService pool = Executors.newFixedThreadPool(2)改为ExecutorService pool = Executors.newSingleThreadExecutor();

    输出结果:

    1. pool-1-thread-1正在执行。。。  
    2. pool-1-thread-1正在执行。。。  
    3. pool-1-thread-1正在执行。。。  
    4. pool-1-thread-1正在执行。。。  
    5. pool-1-thread-1正在执行。。。  

    可以看出,每次调用execute方法,其实最后都是调用了thread-1的run方法。

    三、可变尺寸的线程池,newCachedThreadPool:

    与上面的类似,只是改动下pool的创建方式:ExecutorService pool = Executors.newCachedThreadPool();


    输出:

    1. pool-1-thread-1正在执行。。。  
    2. pool-1-thread-2正在执行。。。  
    3. pool-1-thread-4正在执行。。。  
    4. pool-1-thread-3正在执行。。。  
    5. pool-1-thread-5正在执行。。。  


    这种方式的特点是:可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。

    四、延迟连接池,newScheduledThreadPool:

    1. package app.executors;  
    2.   
    3. import java.util.concurrent.Executors;  
    4. import java.util.concurrent.ScheduledExecutorService;  
    5. import java.util.concurrent.TimeUnit;  
    6.   
    7. /** 
    8.  * Java线程:线程池 
    9.  *  
    10.  * @author 冯小卫 
    11.  */  
    12. public class Test {  
    13.     public static void main(String[] args) {  
    14.         // 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。  
    15.         ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);  
    16.         // 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口  
    17.         Thread t1 = new MyThread();  
    18.         Thread t2 = new MyThread();  
    19.         Thread t3 = new MyThread();  
    20.         // 将线程放入池中进行执行  
    21.         pool.execute(t1);  
    22.         // 使用延迟执行风格的方法  
    23.         pool.schedule(t2, 1000, TimeUnit.MILLISECONDS);  
    24.         pool.schedule(t3, 10, TimeUnit.MILLISECONDS);  
    25.   
    26.         // 关闭线程池  
    27.         pool.shutdown();  
    28.     }  
    29. }  
    30.   
    31. class MyThread extends Thread {  
    32.     @Override  
    33.     public void run() {  
    34.         System.out.println(Thread.currentThread().getName() + "正在执行。。。");  
    35.     }  
    36. }  


    读者可以尝试改变Executors.newScheduledThreadPool(2)的参数来得到更多的体验,当然,让

    1. @Override  
    2. public void run() {  
    3.     System.out.println(Thread.currentThread().getName() + "正在执行。。。");  
    4. }  

    变成一个无限循环,你可以得到更多的关于pool.shutdown()的用法。

    五:单任务延迟连接池(和上面类似,就不写了)。当然我们也可以自定义线程池,这里就不写了,累啊……

  • 相关阅读:
    联想 Vibe Shot(Z90-3) 免recovery 获取ROOT权限 救砖 VIBEUI V3.1_1625
    联想 Z5S(L78071)免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 10.5.370
    联想 Z5(L78011) 免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 10.5.254
    联想 S5 Pro(L78041)免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 5.0.123
    第二阶段 冲刺八
    第二阶段 冲刺七
    第二阶段 冲刺六
    第二阶段 冲刺五
    代码大全阅读笔记03
    学习进度十二
  • 原文地址:https://www.cnblogs.com/yaowen/p/5446002.html
Copyright © 2011-2022 走看看