`
ygxu
  • 浏览: 78872 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

jdk5线程池的简单使用

    博客分类:
  • java
阅读更多
一、简介
线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)

corePoolSize: 线程池维护线程的最少数量
maximumPoolSize:线程池维护线程的最大数量
keepAliveTime: 线程池维护线程所允许的空闲时间
unit: 线程池维护线程所允许的空闲时间的单位
workQueue: 线程池所使用的缓冲队列
handler: 线程池对拒绝任务的处理策略

一个任务通过 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是 Runnable类型对象的run()方法。

当一个任务通过execute(Runnable)方法欲添加到线程池时:

如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。

如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。

也就是:处理任务的优先级为:
核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:
NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。

workQueue我常用的是:java.util.concurrent.ArrayBlockingQueue

handler有四个选择:
ThreadPoolExecutor.AbortPolicy()
抛出java.util.concurrent.RejectedExecutionException异常
ThreadPoolExecutor.CallerRunsPolicy()
重试添加当前的任务,他会自动重复调用execute()方法
ThreadPoolExecutor.DiscardOldestPolicy()
抛弃旧的任务
ThreadPoolExecutor.DiscardPolicy()
抛弃当前的任务




二、一般用法举例
//------------------------------------------------------------
//TestThreadPool.java
//package cn.simplelife.exercise; 
import java.io.Serializable;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThreadPool {

private static int produceTaskSleepTime = 2;
private static int consumeTaskSleepTime = 2000;
private static int produceTaskMaxNumber = 10;

public static void main(String[] args) {

//构造一个线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
new ThreadPoolExecutor.DiscardOldestPolicy());

for(int i=1;i<=produceTaskMaxNumber;i++){
try {
//产生一个任务,并将其加入到线程池
String task = "task@ " + i;
System.out.println("put " + task);
threadPool.execute(new ThreadPoolTask(task));

//便于观察,等待一段时间
Thread.sleep(produceTaskSleepTime);
} catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* 线程池执行的任务
* @author hdpan
*/
public static class ThreadPoolTask implements Runnable,Serializable{
private static final long serialVersionUID = 0;
//保存任务所需要的数据
private Object threadPoolTaskData;

ThreadPoolTask(Object tasks){
this.threadPoolTaskData = tasks;
}
public void run(){
//处理一个任务,这里的处理方式太简单了,仅仅是一个打印语句
System.out.println("start .."+threadPoolTaskData);
try {
////便于观察,等待一段时间
Thread.sleep(consumeTaskSleepTime);
} catch (Exception e) {
e.printStackTrace();
}
threadPoolTaskData = null;
}
public Object getTask(){
return this.threadPoolTaskData;
}
}
}
//------------------------------------------------------------
说明:
1、在这段程序中,一个任务就是一个Runnable类型的对象,也就是一个ThreadPoolTask类型的对象。

2、一般来说任务除了处理方式外,还需要处理的数据,处理的数据通过构造方法传给任务。

3、在这段程序中,main()方法相当于一个残忍的领导,他派发出许多任务,丢给一个叫 threadPool的任劳任怨的小组来做。

这个小组里面队员至少有两个,如果他们两个忙不过来,任务就被放到任务列表里面。

如果积压的任务过多,多到任务列表都装不下(超过3个)的时候,就雇佣新的队员来帮忙。但是基于成本的考虑,不能雇佣太多的队员,至多只能雇佣 4个。

如果四个队员都在忙时,再有新的任务,这个小组就处理不了了,任务就会被通过一种策略来处理,我们的处理方式是不停的派发,直到接受这个任务为止(更残忍!呵呵)。

因为队员工作是需要成本的,如果工作很闲,闲到 3SECONDS都没有新的任务了,那么有的队员就会被解雇了,但是,为了小组的正常运转,即使工作再闲,小组的队员也不能少于两个。

4、通过调整 produceTaskSleepTime和 consumeTaskSleepTime的大小来实现对派发任务和处理任务的速度的控制,改变这两个值就可以观察不同速率下程序的工作情况。

5、通过调整4中所指的数据,再加上调整任务丢弃策略,换上其他三种策略,就可以看出不同策略下的不同处理方式。

6、对于其他的使用方法,参看jdk的帮助,很容易理解和使用。
分享到:
评论

相关推荐

    java线程池概念.txt

    3:对线程池的基本使用及其部分源码的分析(注意:这里的源码分析是基于jdk1.6;) a:线程池的状态 volatile int runState; static final int RUNNING = 0; 运行状态 static final int SHUTDOWN = 1; 关闭状态;...

    更好的使用Java线程池

    这篇文章结合Doug Lea大神在JDK1.5提供的JCU包,分别从线程池大小参数的设置、工作线程的创建、空闲线程的回收、阻塞队列的使用、任务拒绝策略、线程池Hook等方面来了解线程池的使用,其中涉及到一些细节包括不同...

    Java中的线程与线程池.pptx

    本文档对Java中的线程和线程池进行了简单介绍。首先,阐述了为什么需要线程、...然后,介绍了为什么需要线程池,JDK自带的线程池实现方式ThreadPoolExecutor的使用及其原理,最后强调ThreadPoolExecutor应用的注意点。

    jdk7新特性jdk8新特性

    # jdk7新特性 ## try-with-resources 是一种声明了`一种或多种资源的try语句`。资源是指在程序用完了之后必须要关闭的对象。try-with-resources语句保证了每个声明了的`资源在语句结束的时候都会被关闭`。任何实现...

    tcp_thread_java.zip_Java 线程池_java TCP线程

    java简单线程池的实现,使用jdk的Executors.newFixedThreadPool方法来实现固定大小线程池

    ThreadsPoolBuilder工具类

    阿里的代码规范中提出,不推荐使用JDK提供的线程池创建方法(newCachedThreadPool、newFixedThreadPool等),因此对ThreadsPoolExecutor方法进行了简单封装,以方便使用。

    ThreadPoolBuilder工具类

    阿里的代码规范中提出,不推荐使用JDK提供的线程池创建方法(newCachedThreadPool、newFixedThreadPool等),因此对ThreadPoolExecutor方法进行了简单封装,以方便使用。

    Java JDK实例宝典

    全部代码出自电子工业出版社夏先波的《Java JDK实例宝典》一书,本书以J2SE 5.0为开发环境,选取Java应用的典型实例,循序渐进地介绍了Java语言的各种开发方法和技巧,实例代码注释详细规范,思路清晰。 第1章 ...

    MThread:实现线程池已有的功能,同时对线程池的本身的使用与运行情况提供监控;与ILog组件配合使用,可以实现线程上下文的自动切换

    普通JDK自带的线程池时无法实现线程池的自动切换,基于监控与上下文自动切换的需求,封住了一套taxi开头的线程池,接入方式很简单,它的使用方式与Jdk的使用基本方式一致,只需在对应的类前加一个Taxi,现将对应方式...

    简单的JAVA HTML服务器

    简单的JAVA HTML服务器 实现原理为采用Socket原理、线程池、输入输出流及简单的HTTP协议...JAR编译的JDK版本1.6,至少要JDK1.5以上,因为其中用到JDK自带的线程池,内附源码,用户可以自已将源码再打包。 下载路径为:

    基于Spring打造简单高效通用的异步任务处理系统

    l Spring封装Job调度:当任务信息都持久化在DB中之后,我们需要将这些信息读取出来执行具体的业务逻辑操作,这里我们...为了让系统更加轻量级,这里我们直接采用Spring中基于JDK线程池的默认封装实现,通过配置调整参数

    Java并发编程原理与实战

    JDK5提供的原子类的操作以及实现原理.mp4 Lock接口认识与使用.mp4 手动实现一个可重入锁.mp4 AbstractQueuedSynchronizer(AQS)详解.mp4 使用AQS重写自己的锁.mp4 重入锁原理与演示.mp4 读写锁认识与原理.mp4 细读...

    java 多线程 生产者消费者模式源码

    java 多线程 生产者消费者模式,多个生产者对多个消费者,使用jdk 线程池及 BlockingQueue实现,解决了待生产的任务生产完成后,正常终止所有线程,避免线程(特别是消费者线程)因阻塞而无限等待的情况。源码中还简单...

    java jdk实列宝典 光盘源代码

    使用smtp协议发送简单邮件; 发送带附件的邮件; 给多人发送邮件; 使用pop3接收邮件; 19jsp与servlet 获取客户端的真实ip地址; jsp无刷新聊天室; 设置和读取cookie; 上传文件; 用servlet生成图形验证码; 用servlet...

    transfertable-thread-local::pushpin:TransmittableThreadLocal(TTL),缺少框架中间件的Java:trade_mark:std lib(简单和0依赖),提供了增强的InheritableThreadLocal,即使使用线程池组件也可以在线程之间传输值

    :pushpin: TransmittableThreadLocal(TTL) :pushpin: ...但对于使用线程池等会池化线程化的执行组件的情况,线程由线程池创建好,并且线程是池化起来反复使用的;这时父子线程关系的ThreadLocal值传

    java并发编程

    第8节多种创建线程的方式案例演示(二)使用线程池00:15:40分钟 | 第9节Spring对并发的支持:Spring的异步任务00:11:10分钟 | 第10节使用jdk8提供的lambda进行并行计算00:14:22分钟 | 第11节了解多线程所带来的...

    Java 的线程工厂 ThreadFactory原理及源码详解

    在JDK的源码使用工厂模式,ThreadFactory就是其中一种。 在我们一般的使用中,创建一个线程,通常有两种方式: 继承Thread类,覆盖run方法,实现我们需要的业务 继承Runnable接口,实现run方法,实现我们需要的业务,...

    龙果 java并发编程原理实战

    第8节多种创建线程的方式案例演示(二)使用线程池00:15:40分钟 | 第9节Spring对并发的支持:Spring的异步任务00:11:10分钟 | 第10节使用jdk8提供的lambda进行并行计算00:14:22分钟 | 第11节了解多线程所带来的...

    Java 并发编程原理与实战视频

    第8节多种创建线程的方式案例演示(二)使用线程池00:15:40分钟 | 第9节Spring对并发的支持:Spring的异步任务00:11:10分钟 | 第10节使用jdk8提供的lambda进行并行计算00:14:22分钟 | 第11节了解多线程所带来的...

Global site tag (gtag.js) - Google Analytics