本文转自: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. 测试EF6.1.3和OrmLite性能

    公司原来用nhibernate,现在考虑要不要换一种ORM,于是找来了EF和ServiceStack.OrmLite.所以就产生了测试这三个性能的要求.对比三个ORM工具的性能,主要是对比ORM配置和 ...

  2. C#3.0扩展方法学习篇

     什么是类的扩展方法 扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. MSDN Extension methods enable you to &q ...

  3. Oracle like查询

    查询方式:LIKE '%xx%' 普通: SELECT * FROM TABLE T WHERE T.COLUNM LIKE '%xx%' 优化:使用 INSTR SELECT * FROM TABL ...

  4. canvas初探2

    2.2 canvas的绘图环境 canvas仅仅只是一个绘图的容器,其内存在一个绘图环境,该环境对象提供了全部的绘图功能. 目前canvas的绘图环境是2d,但canvas规范在着手准备支持其他类型的 ...

  5. Ubuntu添加开机自动启动程序方法

    1. 开机启动时自动运行程序  Linux加载后, 它将初始化硬件和设备驱动, 然后运行第一个进程init.init根据配置    文件继续引导过程,启动其它进程.通常情况下,修改放置在      / ...

  6. Python Django Apache配置

    项目结构目录: Apache 安装配置目录: C:\Apache2.2\conf\httpd.conf LoadModule wsgi_module modules/mod_wsgi.soWSGISc ...

  7. 体验 ASP.NET Core 1.1 中预编译 MVC Razor 视图

    这是从 ASP.NET Core 1.1 官方发布博文中学到的一招,可以在 dontet publish 时将 Razor 视图编译为 .dll 文件. 需要在 project.json 中添加如下配 ...

  8. NoSQL初探之人人都爱Redis:(2)Redis API与常用数据类型简介

    一.Redis API For .Net 首先,不得不说Redis官方提供了众多的API开发包,但是目前Redis官方版本不支持.Net直接进行连接,需要使用一些第三方的开源类库.目前最流行的就是Se ...

  9. 玩转Windows服务系列——Windows服务启动超时时间

    最近有客户反映,机房出现断电情况,服务器的系统重新启动后,数据库服务自启动失败.第一次遇到这种情况,为了查看是不是断电情况导致数据库文件损坏,从客户的服务器拿到数据库的日志,进行分析. 数据库工作机制 ...

  10. Orchard 微软CMS项目介绍

    我之前的项目中使用了Orchard, 它依据依赖注入的思想而做的模块化让我深深为之着迷,这里开始宣传一下这个架构. 包含的概念非常之多,我现在也不甚了解.Orchard就是自己想控制它改变它的话需要非 ...