线程池

来源:互联网 发布:什么云计算 编辑:程序博客网 时间:2024/06/06 02:24
一.概念
在创建对象和销毁对象时需要耗费很大的资源,如果一个程序中有大量线程要执行,每次都要重新创建一个对象的话,会耗费很多
的资源。如果完成一个任务需要的时间分配为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。因为T1和T3
的时间是跟任务执行没有关系的时间,我们就可以想办法可以减少T1和T3的时间,这时候我们就可以用线程池来进行性能优化。
线程池中的线程可以复用,从而减小对象的创建和销毁时间。
线程池中有一个队列,不断的去检查有没有任务,如果有就取出队列中最前面的任务执行,如果没有就等待一段时间后再继续检查
是否有任务。
线程池是多线程的,在使用时需要考虑线程安全问题,线程池一般都用单例模式。


二.线程池的分类
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个固定线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。


三.四种类型的线程池的示例代码及运行结果
package javaDemo;


import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class FourTypePool {
public static void main(String[] args) {
// cacheThreadPool();
// fixedThreadPool();
// scheduledThreadPool();
// scheduledThreadPool2();
singleThreadPool();
}


/**
* 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
*/
public static void singleThreadPool() {
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
int index = i;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
singleThreadPool.execute(new Runnable() {


@Override
public void run() {
System.out.println(index + "==singleThreadPool===" + Thread.currentThread().getName() + "执行");
}
});


}
}
//执行结果
// 0==singleThreadPool===pool-1-thread-1执行
// 1==singleThreadPool===pool-1-thread-1执行
// 2==singleThreadPool===pool-1-thread-1执行
// 3==singleThreadPool===pool-1-thread-1执行
// 4==singleThreadPool===pool-1-thread-1执行
// 5==singleThreadPool===pool-1-thread-1执行
// 6==singleThreadPool===pool-1-thread-1执行
// 7==singleThreadPool===pool-1-thread-1执行
// 8==singleThreadPool===pool-1-thread-1执行
// 9==singleThreadPool===pool-1-thread-1执行


/**
* 创建一个定长线程池,支持定时及周期性任务执行。定期执行,延迟2秒,每3秒执行一次
*/
public static void scheduledThreadPool2() {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
// scheduledThreadPool.scheduleAtFixedRate(command, initialDelay,
// period, unit)
// 第一个参数:任务,第二个参数:延迟时间,第三个参数:周期
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {


@Override
public void run() {
System.out.println("==scheduledThreadPool2===" + Thread.currentThread().getName() + "执行");


}
}, 1, 3, TimeUnit.SECONDS);
}
//执行结果
// ==scheduledThreadPool2===pool-1-thread-1执行
// ==scheduledThreadPool2===pool-1-thread-1执行
// ==scheduledThreadPool2===pool-1-thread-2执行
// ==scheduledThreadPool2===pool-1-thread-1执行
// ==scheduledThreadPool2===pool-1-thread-3执行
// ==scheduledThreadPool2===pool-1-thread-3执行
// ==scheduledThreadPool2===pool-1-thread-4执行
// ==scheduledThreadPool2===pool-1-thread-4执行
// ==scheduledThreadPool2===pool-1-thread-4执行
// ==scheduledThreadPool2===pool-1-thread-4执行
// ==scheduledThreadPool2===pool-1-thread-3执行
// ==scheduledThreadPool2===pool-1-thread-3执行
// ==scheduledThreadPool2===pool-1-thread-5执行
// ==scheduledThreadPool2===pool-1-thread-2执行
// ==scheduledThreadPool2===pool-1-thread-2执行
// ==scheduledThreadPool2===pool-1-thread-1执行
// ==scheduledThreadPool2===pool-1-thread-1执行
// ==scheduledThreadPool2===pool-1-thread-1执行
// ==scheduledThreadPool2===pool-1-thread-1执行
// ==scheduledThreadPool2===pool-1-thread-2执行
// ==scheduledThreadPool2===pool-1-thread-3执行



/**
* 创建一个定长线程池,支持定时及周期性任务执行。延迟执行,延迟3秒执行
*/
public static void scheduledThreadPool() {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
// scheduledThreadPool.schedule(command, delay, unit);
// 第一个参数:任务,第二个参数:延迟时间
scheduledThreadPool.schedule(new Runnable() {


@Override
public void run() {
System.out.println("==scheduledThreadPool===" + Thread.currentThread().getName() + "执行");
}
}, 3, TimeUnit.SECONDS);


}
// 执行结果
// ==scheduledThreadPool===pool-1-thread-1执行


/**
* 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
*/
public static void fixedThreadPool() {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
int index = i;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fixedThreadPool.execute(new Runnable() {


@Override
public void run() {
System.out.println(index + "==fixedThreadPool===" + Thread.currentThread().getName() + "执行");
}
});
}
}
// 执行结果
// 0==fixedThreadPool===pool-1-thread-1执行
// 1==fixedThreadPool===pool-1-thread-2执行
// 2==fixedThreadPool===pool-1-thread-3执行
// 3==fixedThreadPool===pool-1-thread-1执行
// 4==fixedThreadPool===pool-1-thread-2执行
// 5==fixedThreadPool===pool-1-thread-3执行
// 6==fixedThreadPool===pool-1-thread-1执行
// 7==fixedThreadPool===pool-1-thread-2执行
// 8==fixedThreadPool===pool-1-thread-3执行
// 9==fixedThreadPool===pool-1-thread-1执行


/**
* 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
* 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程
*/
public static void cacheThreadPool() {
ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
int index = i;
// 添加10个线程
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cacheThreadPool.execute(new Runnable() {


@Override
public void run() {
System.out.println(index + "==cacheThreadPool===" + Thread.currentThread().getName() + "执行");
}
});
}
}
// 执行结果
// 0==cacheThreadPool===pool-1-thread-1执行
// 1==cacheThreadPool===pool-1-thread-1执行
// 2==cacheThreadPool===pool-1-thread-1执行
// 3==cacheThreadPool===pool-1-thread-1执行
// 4==cacheThreadPool===pool-1-thread-1执行
// 5==cacheThreadPool===pool-1-thread-1执行
// 6==cacheThreadPool===pool-1-thread-1执行
// 7==cacheThreadPool===pool-1-thread-1执行
// 8==cacheThreadPool===pool-1-thread-1执行
// 9==cacheThreadPool===pool-1-thread-1执行


}


四.线程池的实现


package javaDemo;


import java.util.ArrayList;
import java.util.List;


import javaDemo.ThreadPool.WorkThread;


public class TestThreadPool {
public static void main(String[] args) {
ThreadPool threadPool = ThreadPool.getThreadPol(2);
// threadPool.execute(new Runnable[] { new MyTask(), new MyTask(), new
// MyTask() });
List<Runnable> list = new ArrayList<Runnable>();
list.add(new MyTask());
list.add(new MyTask());
list.add(new MyTask());
list.add(new MyTask());
list.add(new MyTask());
threadPool.execute(list);
System.out.println("销毁前" + threadPool);
// 销毁线程池
threadPool.destory();
System.out.println("销毁后" + threadPool);


}


static class MyTask implements Runnable {


@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行");
}


}


}


package javaDemo;


import java.util.LinkedList;
import java.util.List;


public class ThreadPool {
// 线程池中默认线程个数
private static int pool_num = 3;
// 工作线程
private WorkThread[] workThread;
// 已处理任务数量
private static volatile int finish_task = 0;
// 任务队列,作为一个缓存
private List<Runnable> taskQueue = new LinkedList<Runnable>();
private volatile static ThreadPool threadPool;


// 默认线程个数的线程池
public ThreadPool() {
this(3);
}


public ThreadPool(int setPoolNum) {
ThreadPool.pool_num = setPoolNum;
workThread = new WorkThread[setPoolNum];
// 开启线程池中的线程
for (int i = 0; i < workThread.length; i++) {
workThread[i] = new WorkThread();
workThread[i].start();
}
}


// 获取一个指定线程个数的线程池
public static ThreadPool getThreadPol(int setWorkNum) {
if (setWorkNum <= 0) {
setWorkNum = ThreadPool.pool_num;
}
// 双重校验锁
if (threadPool == null) {
synchronized (ThreadPool.class) {
if (threadPool == null) {
threadPool = new ThreadPool();
}
}
}
return threadPool;
}


// 获取默认线程个数的线程池
public static ThreadPool getThreadPool() {
return getThreadPol(ThreadPool.pool_num);
}


// 执行任务
public void execute(Runnable workThread) {
synchronized (taskQueue) {
taskQueue.add(workThread);
taskQueue.notify();
}
}


// 批量执行任务
public void execute(Runnable[] task) {
synchronized (taskQueue) {
for (int i = 0; i < task.length; i++) {
taskQueue.add(task[i]);
}
taskQueue.notify();
}
}


// 批量执行任务
public void execute(List<Runnable> task) {
synchronized (taskQueue) {
taskQueue.addAll(task);
taskQueue.notify();
}
}


// 销毁线程池
public void destory() {
System.out.println("销毁时");
System.out.println("销毁时 taskQueue是否为空:" + taskQueue.isEmpty());
// 如果还有任务没有执行完
while (!taskQueue.isEmpty()) {
System.out.println("销毁时 taskQueue不为空");
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 工作线程停止工作,并且置空
for (int i = 0; i < workThread.length; i++) {
System.out.println("销毁时停止工作线程 taskQueue是否为空:" + taskQueue.isEmpty());
workThread[i].stopWork();
workThread[i] = null;
}
System.out.println("销毁结束");
}


// 获取工作线程个数
public int getWorkThreadNum() {
return pool_num;
}


// 获取完成任务个数
public int getFinishNum() {
return finish_task;
}


// 等待线程的个数
public int getWaitNum() {
return taskQueue.size();
}


class WorkThread extends Thread {
// 该工作线程是否有效
private boolean isRunning = true;


@Override
public void run() {
Runnable runnable = null;
// 如果工作现场有效,就一直去执行任务
while (isRunning) {
synchronized (taskQueue) {
while (isRunning && taskQueue.isEmpty()) {
try {
// 如果任务队列为空,就等待任务,不断的循环去取任务
taskQueue.wait(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (!taskQueue.isEmpty()) {
// 如果任务队列不为空,就取出队列中最前面的一个任务
runnable = taskQueue.remove(0);
}
// 如果任务不为空,就去执行任务
if (runnable != null) {
runnable.run();
}
// 任务执行完毕
finish_task++;
runnable = null;
}
}
}


public void stopWork() {
// 执行run()方法,工作线程结束
isRunning = false;
}
}


}
运行结果:
Thread-0正在执行
销毁前javaDemo.ThreadPool@15db9742
Thread-0正在执行
销毁时
Thread-0正在执行
销毁时 taskQueue是否为空:false
销毁时 taskQueue不为空
Thread-0正在执行
Thread-0正在执行
销毁时停止工作线程 taskQueue是否为空:true
销毁时停止工作线程 taskQueue是否为空:true
销毁时停止工作线程 taskQueue是否为空:true
销毁结束
销毁后javaDemo.ThreadPool@15db9742
0 0