java 线程池详解及四种线程池用法介绍
来源:互联网 发布:淘宝钻石展位图片尺寸 编辑:程序博客网 时间:2024/06/14 02:50
java 线程池详解
Executor框架是一种将线程的创建和执行分离的机制。它基于Executor和ExecutorService接口,及这两个接口的实现类ThreadPoolExecutor展开,Executor有一个内部线程池,并提供了将任务传递到池中线程以获得执行的方法,可传递的任务有如下两种:通过Runnable接口实现的任务和通过Callable接口实现的任务。在这两种情况下,只需要传递任务到执行器,执行器即可使用线程池中的线程或新创建的线程来执行任务。执行器也决定了任务执行时间。
java提供了四种线程池的实现:
(1)newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
(2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
(3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
(4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
下面就对这些线程池的使用方式进行简要的代码介绍:
首先是可缓存线程池:
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadPoolDemo {public static void main (String[] args) {ExecutorService cachedThreadPool = Executors.newCachedThreadPool();for(int i = 0; i < 10; i++) {final int index = i;try {Thread.sleep(index*1000);} catch (InterruptedException e) {e.printStackTrace();}cachedThreadPool.execute(new Runnable () {public void run () {System.out.println(index);}});}}}然后是定长线程池:
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadPoolDemo {public static void main (String[] args) {ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);for(int i = 0; i < 10; i++) {final int index = i;fixedThreadPool.execute(new Runnable () {public void run () {System.out.println(index);try {Thread.sleep(2000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});}}}
然后是定长线程池支持定时和周期性任务:
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ThreadPoolDemo {public static void main (String[] args) {ScheduledExecutorService scheduleThreadPool = Executors.newScheduledThreadPool(5);scheduleThreadPool.schedule(new Runnable() {public void run() {System.out.println("delay 3 seconds");}}, 3, TimeUnit.SECONDS);}}最后是:单线程化线程池
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ThreadPoolDemo {public static void main (String[] args) {ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();for(int i = 0; i < 10; i++) {final int index = i;singleThreadExecutor.execute(new Runnable() {public void run() {try {System.out.println(index);Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();} }});}}}
好了四种线程池的使用上面已经介绍完了,现在来看看线程池的原理吧,其中最重要的就是ThreadPoolExecutor类的构造函数,你会有疑惑,上面程序压根没有出现这个ThreadPoolExecutor类啊,其实,如果你追代码到
Executors.newSingleThreadExecutor()中查看你会发现如下代码:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
这四类线程池类底层都是ThreadPoolExecutor类进行初始化的,你不信你可以一个一个点进去看一下,而且我告诉你,四大线程池是通过使用ThreadPoolExecutor构造函数实现的;你看看下面实现就知道了
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize);//这边居然不是直接调ThreadPoolExecutor构造函数,但是我们追一下代码看看下面这个函数你就会明白 }public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());//里面使用了父类的构造函数,下面就是本类和父类的继承关系,看看他的父类是什么,你就明白了 }public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorServiceOK。到这里,你就应该知道我们今天的主角是谁了---------ThreadPoolExecutor好了我们可以来看看这个类的构造函数源码了:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }看见有好多参数啊,现在主要对其中的构造参数进行解释:corePoolSize:核心池大小,意思是当超过这个范围的时候,就需要将新的线程放到等待队列中了即workQueue;maximumPoolSize:线程池最大线程数量,表明线程池能创建的最大线程数keepAlivertime:当活跃线程数大于核心线程数,空闲的多余线程最大存活时间。unit:存活时间的单位workQueue:存放任务的队列---阻塞队列handler:超出线程范围(maximumPoolSize)和队列容量的任务的处理程序我们执行线程时都会调用到ThreadPoolExecutor的execute()方法,现在我们来看看这个方法的源码(就是下面这段代码了,这里面有一些注释解析),我直接来解释一下吧:在这段代码中我们至少要看懂一个逻辑:当当前线程数小于核心池线程数时,只需要添加一个线程并且启动它,如果线程数数目大于核心线程池数目,我们将任务放到workQueue中,如果连workQueue满了,那么就要拒绝任务了。详细的函数我就不介绍了public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /* * Proceed in 3 steps: * * 1. If fewer than corePoolSize threads are running, try to * start a new thread with the given command as its first * task. The call to addWorker atomically checks runState and * workerCount, and so prevents false alarms that would add * threads when it shouldn't, by returning false. * * 2. If a task can be successfully queued, then we still need * to double-check whether we should have added a thread * (because existing ones died since last checking) or that * the pool shut down since entry into this method. So we * recheck state and if necessary roll back the enqueuing if * stopped, or start a new thread if there are none. * * 3. If we cannot queue task, then we try to add a new * thread. If it fails, we know we are shut down or saturated * and so reject the task. */ int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }
- java 线程池详解及四种线程池用法介绍
- java的四种线程池介绍
- Java四种线程池介绍
- 【Java线程】Java线程池ExecutorService四种详解
- JAVA四种线程池详解
- Java线程池及用法
- Java(Android)线程池,介绍new Thread的弊端及Java四种线程池的使用
- java 线程池原理及几种线程池详解
- java 线程池原理及几种线程池详解
- 介绍new Thread的弊端及Java四种线程池的使用
- 介绍new Thread的弊端及Java四种线程池的使用
- 介绍new Thread的弊端及Java四种线程池的使用
- 介绍new Thread的弊端及Java四种线程池的使用
- Java四种线程池的介绍及详细使用代码示例
- Java四种线程池的介绍及详细使用代码示例
- java-Exectors提供的四种基本线程池用法与比较详解
- Java的四种线程池以及参数介绍
- Java 四种线程池的用法分析
- 关于Hibernate报错 “table” is not mapped
- docker中部署dpdk功能验证
- ConstraintLayout的基本使用
- 如何在Qt中使用自己编译好的so库
- sublime text 3 中 SFTP插件 的 配置
- java 线程池详解及四种线程池用法介绍
- BZOJ 2839: 集合计数 容斥原理 组合数学
- 人脸对齐--Unconstrained Face Alignment without Face Detection
- 【ubantu crontab】crontab 无法保存退出,坑死了
- DB-Engines最新11月数据库排名:MariaDB助力_MySQL流行度超越Oracle
- WPF 用户控件 文本框
- 关于安装Cmake软件出现的"undefined reference to symbol 'keypad'"问题
- 递归全排列
- 什么是共享锁和排它锁