Java多线程学习笔记之自定义线程池
什么是线程池
线程池是管理线程的一种机制。在Java中,可以通过Executor
接口及其实现类来创建线程池。线程池的主要作用是优化线程的创建和运行过程。通过创建线程池,可以减少线程创建的开销,并且可以更好地控制线程的运行状态。
创建线程池
基本使用
Java中提供了四种线程池的实现类,它们分别为:
newFixedThreadPool(int n)
:创建一个固定大小的线程池,即线程数量为n个。newCachedThreadPool()
:创建一个大小不固定的线程池,根据需要创建新的线程。newSingleThreadExecutor()
:创建一个只有一个线程的线程池。newScheduledThreadPool(int n)
:创建一个固定大小的线程池,并且支持定时执行任务。
以上四种线程池都位于java.util.concurrent.Executors
类中。
下面是一个基本的使用示例,使用newFixedThreadPool
方法创建固定大小的线程池:
ExecutorService executorService = Executors.newFixedThreadPool(3);
以上代码创建了一个线程数量为3的固定大小的线程池。
自定义线程池
除了上述的四种线程池以外,我们还可以通过ThreadPoolExecutor
类来自定义线程池。
ThreadPoolExecutor
类的构造方法如下:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
参数说明:
corePoolSize
:线程池中的常驻线程数量。maximumPoolSize
:线程池的最大线程数量。keepAliveTime
:线程池中空闲线程的存活时间。unit
:存活时间的时间单位。workQueue
:任务队列。threadFactory
:线程工厂。handler
:任务拒绝策略。
下面是一个自定义线程池的示例:
public class MyThreadPool {
private final ThreadPoolExecutor executor;
public MyThreadPool() {
int corePoolSize = 2;
int maximumPoolSize = 5;
long keepAliveTime = 10;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(5);
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
public void execute(Runnable task) {
executor.execute(task);
}
public void shutdown() {
executor.shutdown();
}
}
以上代码中,我们自定义了一个线程池MyThreadPool
,并且设置了线程池中常驻线程数量为2个,最大线程数量为5个。空闲线程的存活时间为10秒钟,任务队列使用了ArrayBlockingQueue
,大小为5。
线程池的使用
我们可以通过execute
方法来向线程池中提交一个任务:
executorService.execute(new MyTask());
其中,MyTask
是一个实现了Runnable
接口的任务对象。
除此之外,我们还可以通过submit
方法来向线程池中提交一个任务,并且可以获取到该任务的执行结果:
Future<String> future = executorService.submit(new MyCallable());
String result = future.get();
其中,MyCallable
是一个实现了Callable
接口的任务对象,并且可以返回一个String
类型的结果。
任务拒绝策略
当线程池已满,不能再接受新的任务时,我们可以通过设置RejectedExecutionHandler
来指定任务的拒绝策略。ThreadPoolExecutor
提供了四种默认的拒绝策略:
AbortPolicy
:直接丢弃任务,并抛出一个RejectedExecutionException
异常。CallerRunsPolicy
:由调用线程来执行此任务。DiscardOldestPolicy
:直接丢弃最早提交的任务。DiscardPolicy
:直接丢弃当前提交的任务。
除此之外,我们还可以通过自定义RejectedExecutionHandler
来实现自己的任务拒绝策略。
示例1:固定大小线程池的使用
// 创建一个固定大小线程池,线程数量为3个
ExecutorService executorService = Executors.newFixedThreadPool(3);
// 提交10个任务
for (int i = 0; i < 10; i++) {
executorService.execute(new MyTask(i));
}
// 关闭线程池
executorService.shutdown();
以上代码创建了一个线程池,大小为3个。我们向线程池中提交了10个任务,并且在执行完成后关闭了线程池。其中,MyTask
是一个实现了Runnable
接口的任务对象。
示例2:自定义线程池
public class MyTask implements Runnable {
private int taskNum;
public MyTask(int taskNum) {
this.taskNum = taskNum;
}
@Override
public void run() {
System.out.println("正在执行task " + taskNum);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task " + taskNum + " 执行完毕");
}
}
public class TestMyThreadPool {
public static void main(String[] args) {
MyThreadPool threadPool = new MyThreadPool();
// 提交10个任务
for (int i = 0; i < 10; i++) {
threadPool.execute(new MyTask(i));
}
// 关闭线程池
threadPool.shutdown();
}
}
以上代码自定义了一个线程池MyThreadPool
,我们向线程池中提交了10个任务,并且在执行完成后关闭了线程池。其中,MyTask
是一个实现了Runnable
接口的任务对象。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java多线程学习笔记之自定义线程池 - Python技术站