此为我简书的第一篇文章,不是原创。以后尽量会的。
PS:次为在http://blog.csdn.net/u010687392/article/details/49850803 看到的文章,想自己打下,加深下自己的记忆。
Java内置只为我们提供了五种常用的线程池 下面是五个的代码实现的小 demo
固定线程数量的线程池#
/ * 固定线程数量的线程池 1.先执行3个(最大的并发数量是3个)
* 将7个放到线程池中的消息队列中
*/
private static void FixThreadPool() {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("线程:" + threadName + ",正在执行第" + index + "个任务");
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
一共建立了数量为3的线程池,支持最大的并发数量是3。模拟了10个任务让他处理。执行的情况是首先先执行3个任务,后面的7个任务一次进入任务队列中进行等待,在执行完这3个后,在通过FIFO(先进先出的原则)从任务队列中取出并开始执行新的任务,知道最后的任务执行完毕。
作用:该方法返回一个固定线程数量的线程池,该线程池中的线程数量始终不变,即不会再创建新的线程,也不会销毁已经创建好的线程,自始自终都是那几个固定的线程在工作,所以该线程池可以控制线程的最大并发数。
栗子:假如有一个新任务提交时,线程池中如果有空闲的线程则立即使用空闲线程来处理任务,如果没有,则会把这个新任务存在一个任务队列中,一旦有线程空闲了,则按FIFO方式处理任务队列中的任务
只有一个线程的线程池#
/* 创建只有一个线程的线程池,
* 每次只执行一个线程任务
* 多余的任务会保存到一个任务栈中,
* 等待线程处理完后再依次任务队列中的任务
*/
private static void NewSingleThreadPool() {
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
for (int i = 1; i <= 10; i++) {
final int index = i;
singleThreadPool.execute(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("线程:"+threadName+",正在执行第" + index + "个任务");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
每次都会复用次一个线程进行执行任务栈中的任务,效果为依次执行。
其实我们通过newSingleThreadExecutor()和newFixedThreadPool()的方法发现,创建一个singleThreadExecutorPool实际上就是创建一个核心线程数和最大线程数都为1的fixedThreadPool。
作用:该方法返回一个只有一个线程的线程池,即每次只能执行一个线程任务,多余的任务会保存到一个任务队列中,等待这一个线程空闲,当这个线程空闲了再按FIFO方式顺序执行任务队列中的任务。
根据实际情况 而调整线程池中线程数量#
/**
* 一个根据实际情况调整线程池数量的线程池
*/
private static void NewCahceThreadPool() {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 1; i <= 10; i++) {
final int index = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("线程:" + threadName + ",正在执行第" + index + "个任务");
try {
long time = index * 500;
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
当有线程空闲的情况下,用此线程进行执行任务,否则创建新线程执行任务。
**该方法返回一个可以根据实际情况调整线程池中线程的数量的线程池。即该线程池中的线程数量不确定,是根据实际情况动态调整的。
栗子:假如该线程池中的所有线程都正在工作,而此时有新任务提交,那么将会创建新的线程去处理该任务,而此时假如之前有一些线程完成了任务,现在又有新任务提交,那么将不会创建新线程去处理,而是复用空闲的线程去处理新任务。那么此时有人有疑问了,那这样来说该线程池的线程岂不是会越集越多?其实并不会,因为线程池中的线程都有一个“保持活动时间”的参数,通过配置它,如果线程池中的空闲线程的空闲时间超过该“保存活动时间”则立刻停止该线程,而该线程池默认的“保持活动时间”为60s。 也就是说如果该线程在60s之内没有动作,则进行销毁。 **
可以定时或者周期性执行任务的线程池#
/**
* 一个可以定时或者周期性执行任务的线程池
*/
private static void NewScheDuledThreadPool() {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
// 延迟2秒后执行该任务
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
}
}, 2, TimeUnit.SECONDS);
// 延迟1秒后,每隔2秒执行一次该任务
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
}
}, 1, 2, TimeUnit.SECONDS);
}
作用:该方法返回一个可以控制线程池内线程定时或周期性执行某任务的线程池。
可以定时或者周期性执行任务的线程池,该线程池的线程数为1#
/**
* 创建一个可以定时或者周期性执行任务的线程池,该线程池的线程数为1
*/
private static void newSingleTheadSchedled() {
ScheduledExecutorService singleThreadScheduledPool = Executors.newSingleThreadScheduledExecutor();
// 延迟1秒后,每隔2秒执行一次该任务
singleThreadScheduledPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("线程:" + threadName + ",正在执行");
}
}, 1, 2, TimeUnit.SECONDS);
}
这个和上面的不同的地方就是这个线程池中的线程数量是1
下面是自定义的线程池
Java内置只为我们提供了五种常用的线程池,一般来说这足够用了,不过有时候我们也可以根据需求来自定义我们自己的线程池,而要自定义不同功能的线程池,上面我们也说了线程池功能的不同归根到底还是内部的BlockingQueue实现不同,所以,我们要实现我们自己相要的线程池,就必须从BlockingQueue的实现上做手脚,而上面也说了BlockingQueue的实现类有多个,那么这次我们就选用PriorityBlockingQueue来实现一个功能是按任务的优先级来处理的线程池 链接
扩展线程池
要想扩展线程池的话 就要重写 三个方法