本文转自: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的线程池比较好。

jdk线程池主要原理的更多相关文章

  1. JDK线程池和Spring线程池的使用

    JDK线程池和Spring线程池实例,异步调用,可以直接使用 (1)JDK线程池的使用,此处采用单例的方式提供,见示例: public class ThreadPoolUtil { private s ...

  2. JDK 线程池

    JDK 线程池 线程池参数 在JDK的4种线程池之前, 先介绍一下线程池的几个参数 corePoolSize 线程池的核心线程数量, maximumPoolSize 线程池的最大线程数量 keepAl ...

  3. 自己动手写线程池——向JDK线程池进发

    自己动手写线程池--向JDK线程池进发 前言 在前面的文章自己动手写乞丐版线程池中,我们写了一个非常简单的线程池实现,这个只是一个非常简单的实现,在本篇文章当中我们将要实现一个和JDK内部实现的线程池 ...

  4. jdk线程池ThreadPoolExecutor工作原理解析(自己动手实现线程池)(一)

    jdk线程池ThreadPoolExecutor工作原理解析(自己动手实现线程池)(一) 线程池介绍 在日常开发中经常会遇到需要使用其它线程将大量任务异步处理的场景(异步化以及提升系统的吞吐量),而在 ...

  5. JDK线程池的拒绝策略

    关于新疆服务请求未带入来话原因的问题 经核查,该问题是由于立单接口内部没有成功调用接续的 “更新来电原因接口”导致的,接续测更新来电原因接口编码:NGCCT_UPDATESRFLAG_PUT ,立单接 ...

  6. JDK线程池的使用

    转载自:https://my.oschina.net/hosee/blog/614319: 摘要: 本系列基于炼数成金课程,为了更好的学习,做了系列的记录. 本文主要介绍: 1. 线程池的基本使用 2 ...

  7. juc线程池原理(六):jdk线程池中的设计模式

    一.jdk中默认线程池中的代理模式 单例类线程池只有一个线程,无边界队列,适合cpu密集的运算.jdk中创建线程池是通过Executors类中提供的静态的方法来创建的,其中的单例类线程池的方法如下: ...

  8. JDK线程池的实现

    线程池 接口Executor 该接口只有一个方法,JDK解释如下 执行已提交的Runnable 任务的对象.此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节.调度等)分离开来的方 ...

  9. jdk线程池,使用手记

    Executors----------------------------------------------Executors------------------------------------ ...

随机推荐

  1. 多个table切换 getElementsByClassName

    <!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...

  2. DNS域名服务器

    DNS是用来解析域名的,IP就相当于地址一样,不知道IP就没法访问指定网络.要上PC6下载站,输入www.pc6.com, 得先问问DNS大哥www.pc6.com在哪,然后Dns告诉你后,就上去了w ...

  3. css伪类制作三角箭头

    <meta charset="utf-8"> <style type="text/css"> .tip{ padding: 5px 10 ...

  4. jQuery弹出提示信息简洁版(自动消失)

    之前看了有一些现成的blockUI.Boxy.tipswindow等的jQuery弹出层插件,可是我的要求并不高,只需要在保存后弹出提示信息即可,至于复杂点的弹出层-可以编辑的,我是直接用bootst ...

  5. vue.js 的学习

    官方网站(作者居然是中国人) http://vuejs.org/ Vuex中文手册 http://vuex.vuejs.org Vue-Router 手册 http://router.vuejs.or ...

  6. SQL——行值表达式(Row Value Expressions)

    概述 最近接触了一个新概念——行值表达式,也叫做行值构造器.这是一个很强大的SQL功能,通常我们所操作的SQL表达式都只能针对一行中的单一字段进行操作比较,而行值表达式可以针对一行中的多个字段进行操作 ...

  7. Repeater的分页

      Repeater控件是个好东西.轻量级.又好用.完全的自定义.但是,正是因为这些优点它没有自动分页的功能.这个需要研究一下.我看了一下起点等小说网站,那些什么推荐排名榜用Repeater控件那是很 ...

  8. Ruby 里的 %Q, %q, %W, %w, %x, %r, %s, %i (译)转

    原文地址  转自 %Q 用于替代双引号的字符串. 当你需要在字符串里放入很多引号时候, 可以直接用下面方法而不需要在引号前逐个添加反斜杠 (\") >> %Q(Joe said: ...

  9. C#_基础:委托速讲

    1定义:委托=函数指针 C# public delegate void Test(string str); 等价C++ public void (*Test)(string str): 委托赋值(初始 ...

  10. Python黑帽编程 4.0 网络互连层攻击概述

    Python黑帽编程 4.0 网络互连层攻击概述 是时候重新温习下下面这张图了. 图2 本章的内容核心包含上图中的网络层和传输层.TCP/IP是整个网络协议体系中的核心,因为从这里开始,数据传输从局域 ...