线程与线程池
线程
线程是操作系统能够运算调度的最小单位,它被包含在进程中,是进程中的实际运做单位。
Java创建线程的方式
public class DemoThread extends Thread {
public static void main(String[] args) throws Exception {
//1、继承Thread类
Thread t1 = new DemoThread();
//2、使用Runnable接口
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
//...
}
});
//Thread t2 = new Thread(()->System.out.println(""));
//3、使用Callable
Future<String> future = new FutureTask<String>(new Callable<String>() {
@Override
public String call() {
return null;
}
});
t1.start();
t2.start();
future.get();
}
@Override
public void run() {
//...
}
}
线程池
为什么要使用线程池
- 降低资源的消耗,通过重复利用已创建的线程降低线程创建、销毁线程造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控
线程池参数
/**
* @param corePoolSize 核心线程数
* @param maximumPoolSize 最大线程数
* @param keepAliveTime 非核心线程数最大存活时间
* @param unit 存活时间单位
* @param workQueue Runnable类型的阻塞队列
* @param threadFactory 线程工厂,负责创建线程
* @param handler 工作队列饱和后,任务的拒绝策略
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code threadFactory} or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
拒绝策略
线程池拒绝策略需要实现java.util.concurrent.RejectedExecutionHandler接口,默认提供4种拒绝策略
- CallerRunsPolicy:被拒绝的任务在主线程中运行,所以主线程就被阻塞了。
- AbortPolicy:抛出RejectedExecutionException 异常,也是默认的拒绝策略
- DiscardPolicy:直接丢弃
- DiscardOldestPolicy:丢弃最早进入的任务
使用Executors创建线程池
- newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newSingleThreadExecutor:创建一个单线程化的线程池执行任务。
- newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。
添加任务执行的逻辑
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
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);
}

浙公网安备 33010602011771号