一、线程池概念
每当提到一个新名词的时候总是会从概念入手,我们首先需要知道这个东西是什么?所谓线程池从字面上理解就是一个装载线程的池子或者说装载线程的容器。这个容器中可以装载多个线程,线程的生命周期交给线程池去管理,方便了我们苦逼的程序员。这样的话我们可以对线程池中的线程进行复用,避免了频繁创建线程以及销毁线程的时间与空间上的开销。
二、线程池执行流程

线程池任务执行流程:
1.当线程池小于corePoolSize时,对于新提交的任务线程池会创建一个新线程执行任务,即使该线程池中存在空闲线程。
2.当线程池线程数达到corePoolSize时,新提交的任务将会线程池放入到workQueue中,等到线程池中的任务调度执行。
3.当workQueue已经满了的时候,并且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务。
4.当提交任务数超过maximumPoolSize时,新提交的任务由RejectedExecutionHandler即拒绝策略处理。
5.线程池中超过corePoolSize的线程,如果这些线程空闲时间达到了keepAliveTime时,关闭空闲线程。
6.当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭。
三、线程池中几个重要参数的理解
1.corePoolSize
用于设定 thread pool 需要时刻保持的最小 core threads 的数量,即便这些 core threads 处于空闲状态啥事都不做也不会将它们回收掉,当然前提是你没有设置 allowCoreThreadTimeOut 为 true。
2.maximumPoolSize
用于限定 pool 中线程数的最大值。如果你自己构造了 pool 且传入了一个 Unbounded 的 queue 且没有设置它的 capacity,那么不好意思,最大线程数会永远 <= corePoolSize,maximumPoolSize 变成了无效的。
3.workQueue
该线程池中的任务队列:维护着等待执行的 Runnable 对象。当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务
用来保存等待被执行的任务的阻塞队列,且任务必须实现Runable接口,在JDK中提供了如下阻塞队列:
(1)、ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务;
(2)、LinkedBlockingQuene:基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQuene;
(3)、SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene;
(4)、priorityBlockingQuene:具有优先级的无界阻塞队列;
4.handler(拒绝策略)
线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略:
1、AbortPolicy:直接抛出异常,默认策略;
2、CallerRunsPolicy:用调用者所在的线程来执行任务;
3、DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
4、DiscardPolicy:直接丢弃任务;
四、线程池状态
1.RUNNING:接受新任务并且处理阻塞队列里的任务
2.SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务
3.STOP:拒绝新任务并且抛弃阻塞队列里的任务同时会中断正在处理的任务
4.TIDYING:所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为0,将要调用terminated方法
5.TERMINATED:终止状态。terminated方法调用完成以后的状态
好了看到这里话就不多说了,直接码代码吧!我们今天首先看看四种比较常见的线程池
1.newFixedThreadPool使用示例
/**
* 固定线程数线程池简单使用
*/
public class FixPoolDemo {
private static Runnable getThread(final int i) {
return new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
};
}
public static void main(String[] args) {
ExecutorService fixPool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
fixPool.execute(getThread(i));
}
fixPool.shutdown();
}
}
2.newCachedThreadPool使用示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CachePool {
private static Runnable getThread(final int i) {
return new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
};
}
public static void main(String[] args) {
ExecutorService cachePool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
cachePool.execute(getThread(i));
}
cachePool.shutdown();
}
}
3.newSingleThreadExecutor使用示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SinglePoolDemo {
private static Runnable getThread(final int i) {
return new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
};
}
public static void main(String[] args) {
ExecutorService singlePool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
singlePool.execute(getThread(i));
}
singlePool.shutdown();
}
}
4.newScheduledThreadPool使用示例
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(4000);
System.out.println(Thread.currentThread().getId() + "执行了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},0, 2, TimeUnit.SECONDS);
}
}
今天对于java线程池就做一个简单的介绍,主要对线程池的概念,线程池处理任务的流程以及常见的几种线程池用法做了讲解,明天我们会根据源码进行更加深入的解析。大家有什么建议和见解,欢迎评论交流,我会积极吸取和改进,谢谢!

296

被折叠的 条评论
为什么被折叠?



