权声明:本文为博主原创文章,未经博主允许不得转载。
1 设计思路
多线程技术主要是针对CPU解决高效执行任务的问题,使用多线程技术可以增加CPU的并行处理能力,但是在服务器上创建线程和销毁线程却是比较花费时间的,而线程的执行时间取决于任务的本身。如果在服务器上创建线程和销毁线程的时间之和大于线程的执行时间,那么就可以考虑采用线程池。
线程池这种技术及时为了解决减少线程的创建时间和销毁时间,在客户端的任务请求来到之前,服务器已经创建好了多个线程并把它放在线程池里以供客户端的任务使用,从而提高服务器端的性能。为了达到这种目的,实现线程池主要包括以下4个基本组成部分:
1)线程池管理类
主要用于实现创建线程和添加客户端请求的新任务,执行任务以及如何回收已经执行完任务的线程。
2)工作线程类
线程池中的线程,它主要用于处理任务队列中的任务。
3)任务类
定义任务的各种属性,以及要完成的操作
4)任务队列
按先来先服务的顺序用于存放新加入的任务,以便让工作线程来执行
2 任务队列的实现
任务队列用来存放要处理的任务,它使用了一个集合类,但是集合本质上是非多线程安全的,通常的类Map、Set以及List都不是线程安全的,当多个线程与集合进行数据交互时,为了使多线程安全,必须采取适当的措施,在文中通过Collections.synchronizedList
将其转换为一个线程安全的类。任务队列定义如下所示:
private List<Task> taskQueue = Collections.synchronizedList(new LinkedList<Task>());
3 任务类的实现
任务类(Task)其实就是一个线程类,它实现了Runnable接口,在run()方法里面可以定义任务要完成的操作。主要代码如下:
public class Task implements Runnable{
@override
public void run(){
// 定义任务的操作
}
}
4 工作线程类的实现
工作线程类也是一个线程类,它也实现了Runnable接口,在run()方法里面它首先判断任务队列里面是否有任务,如果没有就等待新任务加入,如果有任务就从任务队列中取出任务并执行,在线程池中可以设定工作线程的个数。在run()方法中的主要代码如下:
while(isRunning){
lock.lock();
while(taskQueue.isEmpty()){
try{
taskQueue.wait();
}catch(Exception e){
}
}
task = (Task)taskQueue.remove(0);
try{
new Thread(task).start();
}catch(Exception e){
e.printStackTrace();
}
lock.unlock();
}
5 线程池管理类的实现
线程池管理类的实现采用了单例设计模式,单例设计模式是一种常用的软件设计模式。提供了对唯一实例的访问方式。通过单例设计模式可以保证系统中一个类只有一个实例被外界访问,对于线程池来说,单例设计模式是最好的实现。在线程池管理类中主要有增加任务的方法(addTask)、批量增加任务的方法(batchAddTask)、得到实例的方法(getInstanse)以及执行任务的方法(execute),主要代码如下:
//增加任务的方法
public void addTask(Task task){
lock.lock();
taskQueue.add(task);
taskQueue.notifyAll();
lock.unlock();
}
//执行任务的方法
public void execute(){
for(int i=0; i<workThreads.length; i++){
WorkThread wt = workThreads[i];
if(wt.isWaiting()){
new Thread(wt).start();
break;
}
}
}
6 结语
通过上面的介绍,可以很容易把线程池应用在服务器对客户端任务的管理,通过运用线程池,可以提高线程资源的使用率,从而提高系统的效率。