目录
一、线程池
昨天使用了数据库连接池,我们了解了连接池的优点,那么也可以使用线程池来管理线程,
java自带的线程池的参数有 核心线程数,最大线程数,线程活跃时间,时间单位,任务队列,线程工厂,拒绝策略
为了学习了解线程池,我们先手写一个简单的线程池,只需要做到核心线程可重复利用就行
1. 构建线程池的类
属性:核心线程数,任务队列
方法:获取线程(静态代码块),执行任务(需要的参数:线程任务 Runnable)
为了避免创建多个对象,还需要设置单例模式
package com.shao.net;
import java.util.concurrent.LinkedBlockingQueue;
public class ThreadPool {
// 定义一个成员静态变量,存储单例对象
private static ThreadPool instance;
// 线程池核心线程数
private final static int MAX_THREAD_NUM = 10;
// 存放任务的队列
private static final LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
static {
for (int i = 0; i < MAX_THREAD_NUM; i++) {
final int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
/**
* 线程池的线程,从队列中取出任务,这时线程不在临界区了,自动释放锁,然后执行任务,当执行完任务后,
* 因为是while循环,所以会在 synchronized (taskQueue) 等待,
* 当锁释放后,并且当前线程被唤醒时,会尝试获取锁,
* 如果获取到锁,会进入临界区,如果队列中有任务,则取出,然后执行任务,如果没有,则等待
* 等待下次获取到锁,会继续从上次进入等待态的位置继续往下执行,也就是 taskQueue.wait() 开始往下执行
* */
while (true) {
Runnable task = null;
synchronized (taskQueue) {
System.out.println("线程" + finalI + "准备完成");
// 队列为空,等待
while (taskQueue.isEmpty()) {
try {
taskQueue.wait(); // 使当前线程等待,释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程" + finalI + "开始执行");
// 从队列中取出任务
task = taskQueue.poll();
}
if (task != null) {
// 执行任务
task.run();
}
}
}
}).start();
}
}
// 私有化构造函数
private ThreadPool() {
}
// 获取对象
public static ThreadPool getInstance() {
synchronized (ThreadPool.class) {
if (instance == null) {
instance = new ThreadPool();
}
return instance;
}
}
public void execute(Runnable task) {