赞
踩
当我们需要频繁地创建多个线程进行耗时操作时,每次都通过new Thread实现并不是一种好 的方式,每次new Thread新建和销毁对象性能较差,线程缺乏统一管理,可能无限制新建线程, 相互之间竞争,可能占用过多系统资源导致死锁,并且缺乏定时执行、定期执行、线程中断等功能。 好在Java提供了 4种线程池,它能够有效地管理、调度线程,避免过多的资源消耗,它强大到几 乎不需要幵发人员自定义的程度。它的优点如下:
(1) 重用存在的线程,减少对象创建、销毁的幵销;
(2) 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞;
(3) 提供定时执行、定期执行、单线程、并发数控制等功能。
线程池原理简单地解释就是会创建多个线程并且进行管理,提交给线程的任务会被线程池指派给 其中的线程进行执行,通过线程池的统一调度、管理使得多线程的使用更简单、高效。如下图所示。
它的功能是启动指定数量的线程以及将任务添加到一个队列中,并且将任务分发给空闲的线程。ExecutorService 的生命周期包括三种状态:运行、关闭、终止。创建后便进入运行状态,当调用的 shutdown() 方法时,便进入关闭状态,此时意味着 ExecutorService 不再接受新的任务,但它还在执行已提交的任务。当所有已提交的任务执行完后,就变成终止状态。
ThreadPoolExecutor 的构造函数如下:
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable> workQueue,
- RejectedExecutionHandler handler)
下面对这几个参数详细说明:
ThreadPoolExecutor 的使用流程:
- /**
- * 1.创建基本线程池
- * corePoolSize:该线程池中核心线程的数量。
- * maximumPoolSize:最大线程数量
- * keepAliveTime:非核心线程空闲时要等待下一个任务到来的时间
- * unit:上面时间属性的单位
- * workQueue:任务队列
- */
- ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
- 3,
- 5,
- 1,
- TimeUnit.SECONDS,
- new LinkedBlockingQueue<Runnable>(100));
-
- /**
- * 2. 向线程池提交任务:execute()
- */
- threadPool.execute(new Runnable() {
- @Override
- public void run() {
- // 线程执行任务
- }
- });
-
- /**
- * 3. 关闭线程池shutdown()
- * 也可调用shutdownNow()关闭线程:threadPool.shutdownNow()
- * shutdown:设置 线程池的状态 为 SHUTDOWN,然后中断所有没有正在执行任务的线程
- * shutdownNow:设置 线程池的状态 为 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表
- * 使用建议:一般调用shutdown()关闭线程池;若任务不一定要执行完,则调用shutdownNow()
- */
- threadPool.shutdown();
上面介绍的是基本的线程池 ThreadPoolExecutor 简单介绍,但这个并不是常用的;后面会介绍几种常用的线程池,它们都是根据 ThreadPoolExecutor 的基础上延伸的。
启动指定数量的线程池 - FixedThreadPool
定时执行一些任务的线程池 - ScheduledThreadPool
可缓存的线程池 - CachedThreadPool
单个核线的线程池 - SingleThreadExecutor
这里面最常用的线程池是 FixedThreadPool ,下面来分别看一下它们的基本使用
启动指定数量的线程池 - FixedThreadPool
特点:该线程池只有核心线程,不会被回收;一般用于控制线程的最大并发数
- //创建线程池
- public ExecutorService mExecutor = Executors.newFixedThreadPool(5);
-
- //创建线程对象
- public class MyRunnable implements Runnable {
-
- private final int width;
- private final int height;
-
- public MyRunnable(int imageWidth, int imageHeight) {
- this.width = imageWidth;
- this.height = imageHeight;
- }
-
- @Override
- public void run() {
- //逻辑处理
- if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
- Log.e("wqs", "主线程: " + Thread.currentThread().getName());
- } else {
- Log.e("wqs", "不是主线程: " + Thread.currentThread().getName());
- }
- }
- }
-
- //向线程池添加任务
- private synchronized void startRunnable() {
- mExecutor.execute(new MyRunnable(100, 100));
- }
-
- //关闭线程池
- private void stopExecutor(){
- mExecutor.shutdown();
- }
当我们一直调用上面的 startRunnable() 方法时,可以看出最多有五个线程来处理我们的任务,如下图:
定时执行一些任务的线程池 - ScheduledThreadPool
特点:核心线程数量一定,非核心线程数量多个,闲置时会立马回收非核心线程数量;一般用于定时的任务
- //创建线程池
- public ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
-
- //创建线程对象
- public class MyRunnable implements Runnable {
-
- private final int width;
- private final int height;
-
- public MyRunnable(int imageWidth, int imageHeight) {
- this.width = imageWidth;
- this.height = imageHeight;
- }
-
- @Override
- public void run() {
- //逻辑处理
- if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
- Log.e("wqs", "主线程: " + Thread.currentThread().getName());
- } else {
- Log.e("wqs", "不是主线程: " + Thread.currentThread().getName());
- }
- }
- }
-
- //延迟开始执行
- private synchronized void startRunnable() {
- //延迟1s后执行任务
- scheduledExecutorService.schedule(new MyRunnable(100, 100), 1, TimeUnit.SECONDS);
- }
-
- //延迟开始执行循环任务
- private synchronized void startRunnableCycle() {
- //延迟100ms后、每隔1000ms执行任务
- scheduledExecutorService.scheduleAtFixedRate(new MyRunnable(100, 100),100,1000,TimeUnit.MILLISECONDS);
-
- }
-
- //关闭线程池
- private void stopExecutor(){
- scheduledExecutorService.shutdown();
- }
可缓存的线程池 - CachedThreadPool
特点:只有非核心线程,线程数量不固定;一般用于执行大量耗时少的任务
- //创建线程池
- public ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
-
- //创建线程对象
- public class MyRunnable implements Runnable {
-
- private final int width;
- private final int height;
-
- public MyRunnable(int imageWidth, int imageHeight) {
- this.width = imageWidth;
- this.height = imageHeight;
- }
-
- @Override
- public void run() {
- //逻辑处理
- if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
- Log.e("wqs", "主线程: " + Thread.currentThread().getName());
- } else {
- Log.e("wqs", "不是主线程: " + Thread.currentThread().getName());
- }
- }
- }
-
- //开始执行
- private synchronized void startRunnable() {
- cachedThreadPool.execute(new MyRunnable(100, 100));
- }
-
- //关闭线程池
- private void stopExecutor(){
- cachedThreadPool.shutdown();
- }
单个核线的线程池 - SingleThreadExecutor
特点:只有一个核心线程(是一个单线程);一般用于数据库操作
- //创建线程池
- public ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
-
- //创建线程对象
- public class MyRunnable implements Runnable {
-
- private final int width;
- private final int height;
-
- public MyRunnable(int imageWidth, int imageHeight) {
- this.width = imageWidth;
- this.height = imageHeight;
- }
-
- @Override
- public void run() {
- //逻辑处理
- if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
- Log.e("wqs", "主线程: " + Thread.currentThread().getName());
- } else {
- Log.e("wqs", "不是主线程: " + Thread.currentThread().getName());
- }
- }
- }
-
- //开始执行
- private synchronized void startRunnable() {
- singleThreadExecutor.execute(new MyRunnable(100, 100));
- }
-
- //关闭线程池
- private void stopExecutor(){
- singleThreadExecutor.shutdown();
- }
上面是对线程池的简单理解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。