jdk线程池主要原理
本文转自:http://blog.csdn.net/linchengzhi/article/details/7567397
正常创建一个线程的时候,我们是这样的:new thread(Runnable实现类)。这里,thread是线程,Runnable实现类是业务逻辑,这样线程和业务逻辑紧紧绑定在一起。
采用线程池来处理的时候,我们动态生成若干个线程存于池中,但是这些线程要执行那些业务逻辑是不知道的,由于业务逻辑个数和具体的逻辑需要用户来指定,这些是变化的,我们需要自己编写并存于linkedList(linkedList便于删除和增加)。
那线程如何从linkedList中读取一个一个的业务逻辑,比较好的办法就是thread中的run方法来一个while(true)循环,并不断的从linkedList中读取业务逻辑(如:r = (Runnable) queue.removeFirst();),并执行业务逻辑。由于thread中的run方法一上来就写好的,不知道具体的业务逻辑实现类是什么,所以必须使用多态的方式,并传递具体的业务逻辑实现类给基类。
jdk,为了方便编程并减少接口个数,这个基类就采用runnable,这样线程池执行的时候只需要这样,producerPool.execute(new ThreadPoolTask(task)); ThreadPoolTask实现了runnable接口。
参考如下代码:
具有线程池的工作队列:http://www.ibm.com/developerworks/cn/java/j-jtp0730/
public class WorkQueue { private final int nThreads; private final PoolWorker[] threads; private final LinkedList queue; public WorkQueue(int nThreads) { this.nThreads = nThreads; queue = new LinkedList(); threads = new PoolWorker[nThreads]; for (int i=0; i<nThreads; i++) { threads[i] = new PoolWorker(); threads[i].start(); } } public void execute(Runnable r) { synchronized(queue) { queue.addLast(r); queue.notify(); } } private class PoolWorker extends Thread { public void run() { Runnable r; while (true) { synchronized(queue) { while (queue.isEmpty()) { try { queue.wait(); } catch (InterruptedException ignored) { } } r = (Runnable) queue.removeFirst(); } // If we don't catch RuntimeException, // the pool could leak threads try { r.run(); } catch (RuntimeException e) { // You might want to log something here } } } } } |
还可参考:http://newleague.iteye.com/blog/1124024
使用jdk线程池代码,已经测试过,可运行:http://fire11.iteye.com/blog/636454
package cn.simplelife.exercise;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestThreadPool {
private static int produceTaskSleepTime = 2;
public static void main(String[] args) {
// 构造一个线程池
ThreadPoolExecutor producerPool = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new ArrayBlockingQueue(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();
}
}
}
}
package cn.simplelife.exercise;
import java.io.Serializable;
/**
* 线程池执行的任务
*
* @author hdpan
*/
public class ThreadPoolTask implements Runnable, Serializable {
// JDK1.5中,每个实现Serializable接口的类都推荐声明这样的一个ID
private static final long serialVersionUID = 0;
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;
}
}
jdk对线程池做了很好的封装,内有大量同步实现和各种情况的考虑,个人看完源代码,还是觉得用jdk的线程池比较好。
出处:http://www.cnblogs.com/kmsfan
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
欢迎大家加入KMSFan之家,以及访问我的优酷空间!