关于“jdk线程池的实现”的攻略,我们可以分为以下几个部分来讲解:
1. 线程池原理和作用
线程池是一种常用的异步并发编程技术。其作用是在程序运行时提前创建一定数量的线程,这些线程被用来执行一些任务,一旦任务执行完毕,线程不会被销毁,而是等待被下一个任务调用。这样可以减少线程的创建和销毁,提高程序的性能和稳定性。
2. jdk线程池的实现
在JDK中,提供了一个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
:拒绝策略,用于处理任务队列已满的情况。
例如,我们可以这样创建一个线程池:
ExecutorService threadPool = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
其中,我们使用了默认的线程工厂和拒绝策略,而任务队列使用了无界阻塞队列。
3. 示例说明
下面我们来看两个示例,分别演示了线程池的基本用法和拒绝策略的应用。
示例1:基本用法
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadPoolDemo {
static class Task implements Runnable {
private int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("task " + taskId + " running on thread " + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++) {
threadPool.execute(new Task(i));
}
threadPool.shutdown();
}
}
在这个示例中,我们通过Executors.newFixedThreadPool(2)
来创建一个固定大小为2的线程池。然后,我们创建5个任务并提交给线程池,这时线程池会开启两个线程来执行任务。由于线程池的大小为2,因此只会有两个任务同时执行,而其他任务会被放入任务队列中等待空闲线程的执行。最后,我们调用shutdown()
方法来关闭线程池。
输出结果如下:
task 0 running on thread pool-1-thread-1
task 1 running on thread pool-1-thread-2
task 2 running on thread pool-1-thread-1
task 3 running on thread pool-1-thread-2
task 4 running on thread pool-1-thread-1
可以看到,线程池中一共有两个线程在执行任务,并且任务的执行顺序与提交顺序不一定相同。
示例2:拒绝策略
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class RejectedExecutionDemo {
static class Task implements Runnable {
private int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task " + taskId + " running on thread " + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2), ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 6; i++) {
threadPool.execute(new Task(i));
}
threadPool.shutdown();
}
}
在这个示例中,我们创建了一个容量为2的有界任务队列,并将其作为线程池的任务队列。另外,我们将线程池的最大线程数设置为4,这样线程池一共可以同时执行6个任务。
然后,我们创建6个任务并提交给线程池,这时先执行的两个任务会被分配到空闲的线程中执行;而后续的四个任务则会被放入任务队列中等待执行。此时,任务队列已经满了,而线程池中的线程已经达到了最大值,因此新的任务不再被接受,而是由拒绝策略来处理。在这个示例中,我们使用了默认的拒绝策略ThreadPoolExecutor.AbortPolicy()
,它会直接抛出RejectedExecutionException
异常。因此,在这个示例中,最后两个任务都无法被执行。
输出结果如下:
task 0 running on thread pool-1-thread-1
task 1 running on thread pool-1-thread-2
task 2 running on thread pool-1-thread-1
task 3 running on thread pool-1-thread-2
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@15bb7f69 rejected from java.util.concurrent.ThreadPoolExecutor@6d06d69c[Running, pool size = 4, active threads = 4, queued tasks = 2, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at com.example.demo.RejectedExecutionDemo.main(RejectedExecutionDemo.java:32)
可以看到,在task 4
和task 5
被拒绝执行,并抛出了RejectedExecutionException
异常。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:jdk线程池的实现 - Python技术站