本文转自: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. JS 的事件委托机制

    以前写上图所示的鼠标点击触发事件,一般都是用如下所示的给每一个表示列表的标签绑定一个click事件(演示用的例子的框架是React): 毫无疑问,这样是比较繁琐的,以后维护修改改个函数名什么的还不方便 ...

  2. ELK+Kafka集群日志分析系统

    ELK+Kafka集群分析系统部署 因为是自己本地写好的word文档复制进来的.格式有些出入还望体谅.如有错误请回复.谢谢! 一. 系统介绍 2 二. 版本说明 3 三. 服务部署 3 1) JDK部 ...

  3. 安装windows server 2012 r2 的那点事儿

    windows server 2012 r2 安装无法找到install.wim 错误代码0x80070026,以及制作U启动盘决解ISO文件超过5G大小限制的解决方案 用UltaISO刻录后,sou ...

  4. 在VisualStadio2015上使用EF6.0建立MySql数据库

    1.新建工程 2.建立类的文件夹DAL 3.建立相关类 [Student类] using System;using System.Collections.Generic;using System.Li ...

  5. Js中变量的作用域

    一.理解函数作用域需要理解以下几点:    1.函数变量的作用域有全局变量和局部变量两种,全局变量写在函数的最前面,局部变量写在函数体内,局部变量省略了var 也就默认成为了全局变量!    2.函数 ...

  6. canvas初探3:画方画圆

    绘制矩形的方法,strokeRect().fillRect()及clearRect(). 方法 描述 strokeRect(double x,double y,double w,double h) 使 ...

  7. "SQL Server does not handle comparison of NText, Text, Xml, or Image data types."

    "SQL Server does not handle comparison of NText, Text, Xml, or Image data types." sql2000 ...

  8. 使用Junit等工具进行单元测试

    一.类的定义: 类是同一事物的总称,类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类. 二.Junit工具的使用: 1.首先新建一个项目叫JUnit_Test,我们编写一个 ...

  9. SQL Server 事件通知(Event notifications)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 基础知识(Rudimentary Knowledge) 事件通知监控DDL(NotifyQue ...

  10. [.net 面向对象程序设计进阶] (22) 团队开发利器(一)简单易用的代码管理工具VSS

    [.net 面向对象程序设计进阶] (22) 团队开发利器(一)简单易用的代码管理工具VSS 本篇要点:在进阶篇快要结束的时候说说源代码管理器,我们的开发,不是一个人可以完成的事,团队协作很重要,而且 ...