Java线程:新特征-线程池

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

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

Java通过Executors提供四种线程池,分别为:
  newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  newFixedThreadPool :创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。
  newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()

一、 固定大小的线程池 newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        // 创建一个可重用固定线程数的线程池
        ExecutorService pool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int index = i;
            pool.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName() + "  " + index);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        // 关闭线程池
        pool.shutdown();
    }
}

执行结果:

pool-1-thread-3  2
pool-1-thread-2  1
pool-1-thread-1  0
pool-1-thread-1  3
pool-1-thread-2  5
pool-1-thread-3  4
pool-1-thread-2  7
pool-1-thread-1  6
pool-1-thread-3  8
pool-1-thread-1  9

因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。

二、单任务线程池 newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。在上例的基础上改一行创建pool对象的代码为:

//创建一个使用单个 worker线程的 Executor,以×××队列方式来运行该线程。
   ExecutorService pool = Executors.newSingleThreadExecutor();

输出结果为:

pool-1-thread-1  0
pool-1-thread-1  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  6
pool-1-thread-1  7
pool-1-thread-1  8
pool-1-thread-1  9

结果依次输出,相当于顺序执行各个任务。

对于以上两种连接池,大小都是固定的,当要加入的池的线程(或者任务)超过池最大尺寸时候,则入此线程池需要排队等待。

一旦池中有线程完毕,则排队等待的某个线程会入池执行。

三、可变尺寸的线程池

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。与上面的类似,只是改动下pool的创建方式:

// 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        // 创建一个可重用固定线程数的线程池
        ExecutorService pool = Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            final int index = i;
            pool.execute(new Runnable() {
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "  " + index);
                }
            });
        }
        // 关闭线程池
        pool.shutdown();
    }
}

pool-1-thread-1  0
pool-1-thread-6  5
pool-1-thread-5  4
pool-1-thread-10  9
pool-1-thread-4  3
pool-1-thread-3  2
pool-1-thread-2  1
pool-1-thread-9  8
pool-1-thread-8  7
pool-1-thread-7  6

四、延迟连接池

创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "正在执行。。。");
    }
}

public class TestThread {
    public static void main(String[] args) {
        // 创建一个可重用固定线程数的线程池
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
        // 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
        Thread t1 = new MyThread();
        Thread t2 = new MyThread();
        Thread t3 = new MyThread();
        Thread t4 = new MyThread();
        Thread t5 = new MyThread();
        // 将线程放入池中进行执行
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        // 使用延迟执行风格的方法
        pool.schedule(t4, 3, TimeUnit.SECONDS);
        pool.schedule(t5, 3, TimeUnit.SECONDS);
        // 关闭线程池
        pool.shutdown();
    }
}

执行结果:

pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。

Process finished with exit code 0

表示t4,t5延迟3秒执行。

定期执行示例代码如下:

class MyThread extends Thread {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "正在执行。。。");}
}public class TestThread {public static void main(String[] args) {// 创建一个可重用固定线程数的线程池ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);// 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口Thread t1 = new MyThread();Thread t2 = new MyThread();Thread t3 = new MyThread();Thread t4 = new MyThread();Thread t5 = new MyThread();// 将线程放入池中进行执行pool.execute(t1);pool.execute(t2);pool.execute(t3);// 使用延迟执行风格的方法pool.scheduleAtFixedRate(t4, 1, 3, TimeUnit.SECONDS);pool.scheduleAtFixedRate(t5, 1, 3, TimeUnit.SECONDS);}
}

执行结果:

pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。

表示t4,t5延迟1秒后每3秒执行一次。

五、单任务延迟连接池

在四代码基础上,做改动

//创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
   ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();

pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。

Process finished with exit code 0

六、自定义线程池

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
* Java线程:线程池-自定义线程池
*/
publicclass Test {
        public static void main(String[] args) {
                //创建等待队列
                BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);
                //创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
                ThreadPoolExecutor pool = new ThreadPoolExecutor(2,3,2,TimeUnit.MILLISECONDS,bqueue);
                //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
                Thread t1 = new MyThread();
                Thread t2 = new MyThread();
                Thread t3 = new MyThread();
                Thread t4 = new MyThread();
                Thread t5 = new MyThread();
                Thread t6 = new MyThread();
                Thread t7 = new MyThread();
                //将线程放入池中进行执行
                pool.execute(t1);
                pool.execute(t2);
                pool.execute(t3);
                pool.execute(t4);
                pool.execute(t5);
                pool.execute(t6);
                pool.execute(t7);
                //关闭线程池
                pool.shutdown();
        }
}

class MyThread extends Thread {
        @Override
        publicvoid run() {
                System.out.println(Thread.currentThread().getName() + "正在执行。。。");
                try {
                        Thread.sleep(100L);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
        }
}

pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。

Process finished with exit code 0

创建自定义线程池的构造方法很多,本例中参数的含义如下:

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue)

用给定的初始参数和默认的线程工厂及处理程序创建新的ThreadPoolExecutor。使用Executors工厂方法之一比使用此通用构造方法方便得多。

参数:

corePoolSize -池中所保存的线程数,包括空闲线程。

maximumPoolSize -池中允许的最大线程数。

keepAliveTime -当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。

unit - keepAliveTime参数的时间单位。

workQueue -执行前用于保持任务的队列。此队列仅保持由execute方法提交的Runnable任务。

抛出:

IllegalArgumentException -如果 corePoolSize或 keepAliveTime小于零,或者 maximumPoolSize小于或等于零,或者 corePoolSize大于 maximumPoolSize。

NullPointerException -如果workQueue为 null

自定义连接池稍微麻烦些,不过通过创建的ThreadPoolExecutor线程池对象,可以获取到当前线程池的尺寸、正在执行任务的线程数、工作队列等等。

有关Java5线程池的内容到此就没有了,更多的内容还需要研读API来获取.

转载于:https://blog.51cto.com/ciyorecord/1939535

Java线程池(一)相关推荐

  1. 四种Java线程池用法解析

    四种Java线程池用法解析 本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 ...

  2. 面试必问---Java线程池8大拒绝策略

    前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的这个api,大大的简化了多线程代码的开发.而不论你用Fix ...

  3. Java线程池使用与原理

    线程池是什么? 我们可以利用java很容易创建一个新线程,同时操作系统创建一个线程也是一笔不小的开销.所以基于线程的复用,就提出了线程池的概念,我们使用线程池创建出若干个线程,执行完一个任务后,该线程 ...

  4. Java线程池实现原理及其在美团业务中的实践

    来自:美团技术团队 随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流.使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器.J.U.C提供的线程池ThreadPoolExecuto ...

  5. Java线程池详解学习:ThreadPoolExecutor

    Java线程池详解学习:ThreadPoolExecutor Java的源码下载参考这篇文章:Java源码下载和阅读(JDK1.8) - zhangpeterx的博客 在源码的目录java/util/ ...

  6. Java 线程池详解学习:FixedThreadPool,CachedThreadPool,ScheduledThreadPool...

    Java常用的线程池有FixedThreadPool和CachedThreadPool,我们可以通过查看他们的源码来进行学习. Java的源码下载参考这篇文章:Java源码下载和阅读(JDK1.8) ...

  7. JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue .

    2019独角兽企业重金招聘Python工程师标准>>> 从Java5开始,Java提供了自己的线程池.每次只执行指定数量的线程,java.util.concurrent.Thread ...

  8. Java线程池了解一下

    前言 马上就要过年了,还在岗位上坚守"swimming"的小伙伴们顶住.博主给大家带来一篇线程池的基本使用解解闷. 为什么需要使用线程池 1.减少线程创建与切换的开销 在没有使用线 ...

  9. java线程池拒绝策略_Java核心知识 多线程并发 线程池原理(二十三)

    线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后 启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕, 再从队列中取出任务来执行.他 ...

  10. Java 线程池必知的8 大拒绝策略

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | kailing.pub/article/ind ...

最新文章

  1. idea2019配置gradle详解_Java学习之——Gradle的安装配置、IDEA中创建Gradle的Java项目...
  2. 简练软考知识点整理-控制干系人参与
  3. 数据增强之图像旋转及坐标对应(附代码)
  4. mac搭建ios自动化环境之WebDriverAgent配置
  5. java bs架构书_基于BS架构的图书借阅管理模块的分析与设计(JSP+MySQL)(新品)
  6. Java黑皮书课后题第5章:**5.27(显示闰年)编写程序,显示从101到2100期间所有闰年,每行显示10个。数字之间用一个空格字符隔开,同时显示这期间闰年的数目
  7. 10.5~10.6复习与预习的进行
  8. 常用的dos网络命令
  9. 畅聊Java异步编程
  10. android文字识别apk,照片转文字识别提取apk
  11. 如何用一个例子彻底解释白盒测试中语句覆盖、判定覆盖、条件覆盖、条件判定覆盖、条件组合覆盖?
  12. 【SDC】StreamSets实战之路-11-基础篇- StreamSets-数据流开发- Edge数据流设计
  13. 你应该知道的10 种跨域解决方案(附终极方案)
  14. Android插件化方式实现View动态更新
  15. 初识Android 制作一个简单的记账本
  16. python实验一到五作业+自我总结(待更新)
  17. u-boot.lds文件诠释
  18. js简单判断页面是否为手机端访问
  19. 第十章第三节 物体的浮沉条件及应用
  20. 浙江省计算机二级函数,浙江省计算机二级office办公软件Excel函数大全

热门文章

  1. 语音识别技术迎风发展,未来五年规模将近300亿
  2. SAP PM 入门系列2 - IE03显示设备主数据
  3. 人工智能:技术本无罪,善恶在人心
  4. 半小时训练亿级规模知识图谱,亚马逊这个 AI 框架要火
  5. 5G+AI成产业新引擎 安防行业切入点在哪里?
  6. 爱立信将在加拿大建立人工智能实验室
  7. 几十年的领域专家告诉你,机器翻译进化到哪一步了?
  8. Anaconda,pytorch如何安装中文版的BERT和使用
  9. 牛顿法求解非线性方程的根
  10. 北斗定位2.0版来了!普通人手机可用,全免费!