1 为什么要用线程池?
a 单个任务处理的时间很短而请求的数目却是巨大的。
b 每当一个请求到达就创建一个新线程,然后在新线程中为请求服务。
创建一个新线程的开销很大;服务器在创建和销毁线程上花费的时间
和消耗的系统资源要比花在处理实际的用户请求的时间和资源更多。
c 活动的线程也消耗系统资源。
2 线程池的优点
在请求到达时线程已经存在,所以无意中也消除了线程创建所带来的延迟。
这样,就可以立即为请求服务,使应用程序响应更快。
而且,通过适当地调整线程池中的线程数目,也就是当请求的数目超过某个阈值时,
就强制其它任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。
3 使用线程池的风险
死锁 资源不足 并发错误 线程泄漏 请求过载
4 有效使用线程池的准则
调整池的大小
无须编写您自己的池:
用程序开放源码库 util.concurrent ,它包括互斥、信号量、
诸如在并发访问下执行得很好的队列和散列表之类集合类以及几个工作队列实现。
该包中的 PooledExecutor 类是一种有效的、广泛使用的以工作队列为基础的线程池的正确实现。
您无须尝试编写您自己的线程池,这样做容易出错,
相反您可以考虑使用 util.concurrent 中的一些实用程序。
参阅 参考资料以获取链接和更多信息。
util.concurrent 库也激发了 JSR 166,JSR 166
是一个 Java 社区过程(Java Community Process (JCP))工作组,
他们正在打算开发一组包含在 java.util.concurrent 包下的 Java 类库中的并发实用程序,
这个包应该用于 Java 开发工具箱 1.5 发行版。
5 简单线程池至少包含下列组成部分
线程池管理器(ThreadPoolManager):用于创建并管理线程池
工作线程(WorkThread): 线程池中线程
任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
任务队列:用于存放没有处理的任务。提供一种缓冲机制。
简而言之:
1 建任务接口,然后去实现它。
eq:
接口:Business 方法:methods();
TaskBusiness1 重写:methods();
TaskBusiness2 重写:methods();
TaskBusiness3 重写:methods();
2 然后将这些任务tasks放任务队列taskQueue里,工作线程争夺任务队列里的任务。
3 工作线程:run()方法里 synchronized (taskQueue),不住的从队列弹出任务处理。
队列taskQueue == null时,阻塞等待,线程没有死,而是回到线程池。
a 单个任务处理的时间很短而请求的数目却是巨大的。
b 每当一个请求到达就创建一个新线程,然后在新线程中为请求服务。
创建一个新线程的开销很大;服务器在创建和销毁线程上花费的时间
和消耗的系统资源要比花在处理实际的用户请求的时间和资源更多。
c 活动的线程也消耗系统资源。
2 线程池的优点
在请求到达时线程已经存在,所以无意中也消除了线程创建所带来的延迟。
这样,就可以立即为请求服务,使应用程序响应更快。
而且,通过适当地调整线程池中的线程数目,也就是当请求的数目超过某个阈值时,
就强制其它任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。
3 使用线程池的风险
死锁 资源不足 并发错误 线程泄漏 请求过载
4 有效使用线程池的准则
调整池的大小
无须编写您自己的池:
用程序开放源码库 util.concurrent ,它包括互斥、信号量、
诸如在并发访问下执行得很好的队列和散列表之类集合类以及几个工作队列实现。
该包中的 PooledExecutor 类是一种有效的、广泛使用的以工作队列为基础的线程池的正确实现。
您无须尝试编写您自己的线程池,这样做容易出错,
相反您可以考虑使用 util.concurrent 中的一些实用程序。
参阅 参考资料以获取链接和更多信息。
util.concurrent 库也激发了 JSR 166,JSR 166
是一个 Java 社区过程(Java Community Process (JCP))工作组,
他们正在打算开发一组包含在 java.util.concurrent 包下的 Java 类库中的并发实用程序,
这个包应该用于 Java 开发工具箱 1.5 发行版。
5 简单线程池至少包含下列组成部分
线程池管理器(ThreadPoolManager):用于创建并管理线程池
工作线程(WorkThread): 线程池中线程
任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
任务队列:用于存放没有处理的任务。提供一种缓冲机制。
简而言之:
1 建任务接口,然后去实现它。
eq:
接口:Business 方法:methods();
TaskBusiness1 重写:methods();
TaskBusiness2 重写:methods();
TaskBusiness3 重写:methods();
2 然后将这些任务tasks放任务队列taskQueue里,工作线程争夺任务队列里的任务。
3 工作线程:run()方法里 synchronized (taskQueue),不住的从队列弹出任务处理。
队列taskQueue == null时,阻塞等待,线程没有死,而是回到线程池。
4 最后是销毁线程池。
------------------------------
6 代码如下:
接口或抽象类
public abstract class Business
{
protected String info;
abstract boolean methods();
public String getInfo()
{
return info;
}
}
--------------------------------
实现接口或抽象类1
public class TaskBusiness1 extends Business
{
public TaskBusiness1(String info)
{
this.info = info;
}
public String getInfo()
{
return info;
}
@Override
public boolean methods()
{
try
{
//任务的主体业务逻辑
System.out.println("xxxxxxxxxxxxx");
Thread.sleep(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return false;
}
}
------------------------------
实现接口或抽象类2
public class TaskBusiness2 extends Business
{
public TaskBusiness2(String info)
{
this.info = info;
}
public String getInfo()
{
return info;
}
@Override
public boolean methods()
{
try
{
//任务的主体业务逻辑
System.out.println("*************");
Thread.sleep(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return false;
}
}
-----------------------------------
线程池管理器
public class ThreadPoolManager
{
private static ThreadPoolManager instance = null;
private static Object mylock = ThreadPoolManager.class;
/**
* 任务队列
*/
private List<Business> taskQueue = Collections.synchronizedList(new LinkedList<Business>());
/**
* 工作线程(真正执行任务的线程)
*/
private WorkThread[] workQueue;
/**
* 工作线程数量(默认工作线程数量是5)
*/
private static int worker_num = 5;
private ThreadPoolManager()
{
this(5);
}
private ThreadPoolManager(int num)
{
worker_num = num;
workQueue = new WorkThread[worker_num];
for (int i = 0; i < worker_num; i++)
{
workQueue[i] = new WorkThread();
}
}
/**
* 单例
* <功能详细描述>
* @return
* @see [类、类#方法、类#成员]
*/
public static ThreadPoolManager getInstance()
{
synchronized(mylock)
{
if (instance == null)
{
instance = new ThreadPoolManager();
}
return instance;
}
}
/**
* 单个任务放入任务队列
* <功能详细描述>
* @param task
* @see [类、类#方法、类#成员]
*/
public void addTask(Business task)
{
//对任务队列的操作要上锁
synchronized (taskQueue)
{
if (task != null)
{
taskQueue.add(task);
taskQueue.notifyAll();
System.out.println(task.getInfo() + " submit!");
}
}
}
/**
* 批量任务放入任务队列
* <功能详细描述>
* @param tasks
* @see [类、类#方法、类#成员]
*/
public void BatchAddTask(Business[] tasks)
{
//对任务队列的修改操作要上锁
synchronized (taskQueue)
{
for (Business e : tasks)
{
if (e != null)
{
taskQueue.add(e);
taskQueue.notifyAll();
System.out.println(e.getInfo() + " submit!");
}
}
}
}
/**
* 销毁线程池
* <功能详细描述>
* @see [类、类#方法、类#成员]
*/
public void destory()
{
System.out.println("pool begins to destory ...");
for (int i = 0; i < worker_num; i++)
{
workQueue[i].stopThread();
workQueue[i] = null;
}
//对任务队列的操作要上锁
synchronized (taskQueue)
{
taskQueue.clear();
}
System.out.println("pool ends to destory ...");
}
/**
*
* 工作线程
* <功能详细描述>
* @version [版本号, 2014-1-3]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
private class WorkThread extends Thread
{
/**
* 运行状态
*/
private boolean isRuning = true;
/**
* 阻塞状态
*/
private boolean isWaiting = false;
public WorkThread()
{
this.start();
}
/**
* 如果任务进行中时,不能立刻终止线程,需要等待
* 任务完成之后检测到isRuning为false的时候,退出run()方法
* <功能详细描述>
* @see [类、类#方法、类#成员]
*/
public void stopThread()
{
isRuning = false;
}
@Override
public void run()
{
while (isRuning)
{
Business temp = null;
//对任务队列的操作要上锁
synchronized (taskQueue)
{
//任务队列为空,等待新的任务加入
while (isRuning && taskQueue.isEmpty())
{
try
{
taskQueue.wait(20);
}
catch (InterruptedException e)
{
System.out.println("InterruptedException occre...");
e.printStackTrace();
}
}
if (isRuning)
{
temp = taskQueue.remove(0);
}
}
//当等待新任务加入时候,终止线程(调用stopThread函数)造成 temp = null
if (temp != null)
{
//任务的业务方法
isWaiting = false;
temp.methods();
isWaiting = true;
System.out.println(temp.getInfo() + " is finished");
}
}
}
}
}
---------------------------------------------
test:
public class ThreadPoolManagerTest
{
/**
* 任务类别1
*/
public static final String FLAG_BUSINESS1 = "1";
/**
* 任务类别2
*/
public static final String FLAG_BUSINESS2 = "2";
public static void main(String[] args)
{
//7 个任务
Business[] tasks1 = createBatchTask(3, FLAG_BUSINESS1);
Business[] tasks2 = createBatchTask(5, FLAG_BUSINESS2);
//5 个工作线程
ThreadPoolManager pool = ThreadPoolManager.getInstance();
pool.BatchAddTask(tasks1);
pool.BatchAddTask(tasks2);
//pool.destory();
}
/**
* 批量创建工作任务
* <功能详细描述>
* @param n 个数
* @param flag 任务类别
* @return
* @see [类、类#方法、类#成员]
*/
private static Business[] createBatchTask(int n, String flag)
{
Business[] tasks = null;
if (StringUtils.equals(FLAG_BUSINESS1, flag))
{
tasks = new TaskBusiness1[n];
for (int i = 0; i < n; i++)
{
tasks[i] = new TaskBusiness1("task1 id is " + i);
}
}
else
{
tasks = new TaskBusiness2[n];
for (int i = 0; i < n; i++)
{
tasks[i] = new TaskBusiness2("task2 id is " + i);
}
}
return tasks;
}
}
-------------------
结果:
task1 id is 0 submit!
task1 id is 1 submit!
task1 id is 2 submit!
xxxxxxxxxxxxx
xxxxxxxxxxxxx
xxxxxxxxxxxxx
task2 id is 0 submit!
task2 id is 1 submit!
task2 id is 2 submit!
task2 id is 3 submit!
task2 id is 4 submit!
*************
*************
task1 id is 1 is finished
*************
task2 id is 0 is finished
*************
task1 id is 2 is finished
*************
task1 id is 0 is finished
task2 id is 1 is finished
task2 id is 3 is finished
task2 id is 4 is finished
task2 id is 2 is finished