一、API研究
线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
- corePoolSize
线程池维护线程的最少数量
- maximumPoolSiz
线程池维护线程的最大数量
- keepAliveTime
线程池维护线程所允许的空闲时间
- unit
线程池维护线程所允许的空闲时间的单位
- workQueue
线程池所使用的缓冲队列
- handler
线程池对拒绝任务的处理策略
一个任务通过 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是 Runnable类型对象的run()方法。
当一个任务通过execute(Runnable)方法欲添加到线程池时:
- 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
- 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
- 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
- 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
也就是:处理任务的优先级为: 核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性: NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。
workQueue我常用的是:java.util.concurrent.ArrayBlockingQueue
handler有四个选择:
- ThreadPoolExecutor.AbortPolicy()
抛出java.util.concurrent.RejectedExecutionException异常
- ThreadPoolExecutor.CallerRunsPolicy()
由调用者执行这个任务
- ThreadPoolExecutor.DiscardOldestPolicy()
抛弃旧的任务
- ThreadPoolExecutor.DiscardPolicy()
抛弃当前的任务
二、一般用法举例
TestTheadPool主类:
package com.ibm.threadpool;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestThreadPool {
private static int produceTaskSleepTime = 2000;
public static void main(String[] args) {
// 构造一个线程池
ThreadPoolExecutor producerPool = new ThreadPoolExecutor(2, 4, 0,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
new ThreadPoolExecutor.DiscardOldestPolicy());
// 每隔produceTaskSleepTime的时间向线程池派送一个任务。
int i = 1;
while (true) {
try {
Thread.sleep(produceTaskSleepTime);
String task = "task@ " + i;
System.out.println("put " + task);
producerPool.execute(new ThreadPoolTask(task));
i++;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Task:
package com.ibm.threadpool;
import java.io.Serializable;
/**
* 线程池执行的任务
*/
public class ThreadPoolTask implements Runnable, Serializable {
/**
* serialVersionUID, JDK1.5中,每个实现Serializable接口的类都推荐声明这样的一个ID
*/
private static final long serialVersionUID = -2443443826296885045L;
private static int consumeTaskSleepTime = 2000;
private Object threadPoolTaskData;
ThreadPoolTask(Object tasks) {
this.threadPoolTaskData = tasks;
}
// 每个任务的执行过程,现在是什么都没做,除了print和sleep,:)
public void run() {
System.out.println("start .." + threadPoolTaskData);
try {
// 便于观察现象,等待一段时间
Thread.sleep(consumeTaskSleepTime);
} catch (Exception e) {
e.printStackTrace();
}
threadPoolTaskData = null;
}
}
|
分享到:
相关推荐
在这个例子中,我们创建了一个线程池,核心线程数2,最大线程数5,空闲线程存活时间为1秒,工作队列容量为3。然后提交10个任务,每个任务会打印开始和结束的信息,并睡眠一段时间。最后,调用`shutdown()`方法关闭...
线程池的引入始于JDK 1.5,它引入了`java.util.concurrent`包,提供了`Executor`、`ExecutorService`和相关的实现类,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。 线程池的主要作用是限制系统中同时...
本示例将围绕“关于线程的例子”进行深入探讨,结合Eclipse3.3、MyEclipse6以及jdk1.5的软件环境,我们将学习如何在Java中创建、管理及同步线程。 首先,让我们了解线程的基本概念。线程是进程内的一个执行单元,每...
5. **线程池**:从 JDK 1.5 开始,Java 引入了 `ExecutorService` 和 `ThreadPoolExecutor`,允许开发者创建线程池来管理线程。线程池可以有效控制运行的线程数量,避免频繁创建和销毁线程带来的开销,提高系统性能...
全部代码出自电子工业出版社夏先波的《Java JDK实例宝典》一书,本书以J2SE 5.0为开发环境,选取Java应用的典型实例,循序渐进地介绍了Java语言的各种开发方法和技巧,实例代码注释详细规范,思路清晰。 第1章 ...
2. **Lock接口**:JDK 1.5引入了Lock接口,它提供了比synchronized更细粒度的控制,如可重入性、公平性、非阻塞尝试获取锁等功能。ReentrantLock是Lock接口的一个实现,它的使用方式如下: ```java Lock lock = new...
在这个例子中,我们首先创建了一个`ServerBootstrap`实例,并设置了用于处理网络请求的线程池和管道。然后,我们定义了一个管道工厂,用于创建具体的处理管道,该管道包含了编码器、解码器和处理器。最后,我们通过...
3.3.3. bean属性及构造器参数详解 3.3.3.1. 直接量(基本类型、Strings类型等。) 3.3.3.2. 引用其它的bean(协作者) 3.3.3.3. 内部bean 3.3.3.4. 集合 3.3.3.5. Nulls 3.3.3.6. XML-based configuration metadata ...
17.1.2 JavaSE 5.0中固定尺寸线程池的基本知识 374 17.1.3 自定义尺寸固定线程池的使用 375 17.1.4 单任务线程池的使用 377 17.1.5 可变尺寸线程池的使用 378 17.1.6 延迟线程池的使用 380 17.1.7 使用...
4.5.5 JDK1.5提供了foreach循环 91 4.6 深入数组 93 4.6.1 内存中的数组 93 学生提问:为什么有栈内存和堆内存之分? 93 4.6.2 基本类型数组的初始化 95 4.6.3 引用类型数组的初始化 96 4.6.4 没有多维数组 99...