以实例简介Java中线程池的工作特点

什么原因使我们不得不使用线程池?

个人认为主要原因是:短时间内需要处理的任务数量很多

使用线程池的好处:

1.减少在创建和销毁线程上所花的时间以及系统资源的开销
2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存

以下是Java自带的几种线程池:

1、newFixedThreadPool  创建一个指定工作线程数量的线程池。

每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

2、newCachedThreadPool 创建一个可缓存的线程池。

这种类型的线程池特点是:

1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。

2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。

3、newSingleThreadExecutor 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。

单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的 。

4、newScheduleThreadPool  创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。

总结:

一.FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。

二.CachedThreadPool的特点就是在线程池空闲时,即线程池中没有可运行任务时,它会释放工作线程,从而释放工作线程所占用的资源。但是,但当出现新任务时,又要创建一新的工作线程,又要一定的系统开销。并且,在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。

Java线程池 ThreadPoolExecutor使用实例

package com.sondon.mayi.jpool; 

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; 

public class JPoolLearn { 

 private static int produceTaskSleepTime = 3;
 private static int produceTaskMaxNumber = 20; 

 public void testThreadPoolExecutor(){
  /*
   * ThreadPoolExecutor(
   * int corePoolSize, //线程池维护线程的最少数量
   * int maximumPoolSize, //线程池维护线程的最大数量
   * long keepAliveTime, //线程池维护线程所允许的空闲时间
   * TimeUnit unit, //线程池维护线程所允许的空闲时间的单位
   * BlockingQueue<Runnable> workQueue, //线程池所使用的缓冲队列
   * RejectedExecutionHandler handler //线程池对拒绝任务的处理策略 )
   */
  ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
    5,
    10,
    3,
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<Runnable>(10),
    new ThreadPoolExecutor.DiscardOldestPolicy()
    ); 

  for (int i = 1; i <= produceTaskMaxNumber; i++) {
   try {
    // 产生一个任务,并将其加入到线程池
    String task = "task---" + i;
    threadPool.execute(new ThreadPoolTask(task));
    System.out.println("activeCount :"+ threadPool.getActiveCount());
    // 便于观察,等待一段时间
    Thread.sleep(produceTaskSleepTime);
   } catch (Exception e) {
    e.printStackTrace();
   }
  } 

  //查看当前的线程池状况
  while(true){
   try {
    Thread.sleep(3000);
    System.out.println("pool size :"+threadPool.getPoolSize());//线程池中线程数量
    System.out.println("active count :"+threadPool.getActiveCount());//线程池中活动的线程数量
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 } 

 /**
  *
  * @Author 蔡文锋
  * @Data_Time 2015年7月25日 下午4:06:28
  * @Description { 测试不同线程池模式 }
  */
 public void testNewCachedThreadPool(){
  ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newCachedThreadPool();
//  ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newFixedThreadPool(100);
//  ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newScheduledThreadPool(100);
//  ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newSingleThreadExecutor();
  try {
  for (int i = 0; i < 100; i++) {
   // 产生一个任务,并将其加入到线程池
   String task = "task---" + i;
   threadPool.execute(new ThreadPoolTask(task));
   System.out.println("activeCount :");
   // 便于观察,等待一段时间
   Thread.sleep(produceTaskSleepTime); 

   }
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  //查看当前的线程池状况
  while(true){
   try {
    Thread.sleep(3000);
    System.out.println("pool size :"+threadPool.getPoolSize());//线程池中线程数量
    System.out.println("active count :"+threadPool.getActiveCount());//线程池中活动的线程数量
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 } 

 /**
  *
  * @Author 蔡文锋
  * @Data_Time 2015年7月25日 下午4:06:58
  * @Description { 测试callable与runable方法的区别 }
  */
 public void testNewCachedThreadPool_callable(){
  ExecutorService es=Executors.newFixedThreadPool(10);
  try { 

//   String result=es.submit(new MyCallable<String>()).get();
//   System.out.println("callable result :"+result); 

   String result=(String) es.submit(new ThreadPoolTask("")).get();
   System.out.println("runable result :"+result); 

  } catch (InterruptedException | ExecutionException e) {
   e.printStackTrace();
  }
 } 

 public static void main(String[] args) {
  new JPoolLearn().testNewCachedThreadPool();
 }
} 

/**
 * 线程池执行的任务
 */
class ThreadPoolTask implements Runnable {
 private static int consumeTaskSleepTime = 2000;
 // 保存任务所需要的数据
 private Object threadPoolTaskData; 

 ThreadPoolTask(Object tasks) {
  this.threadPoolTaskData = tasks;
 } 

 public void run() {
  System.out.println("start .." + threadPoolTaskData);
  try {
   // Sleep 2秒 模拟耗时操作
   Thread.sleep(consumeTaskSleepTime);
  } catch (Exception e) {
   e.printStackTrace();
  }
  threadPoolTaskData = null;
 } 

 public Object getTask() {
  return this.threadPoolTaskData;
 }
} 

/**
 *
 * @Project : JPool
 * @Package : com.sondon.mayi.jpool
 * @Class : MyCallable
 * @param <T>
 */
class MyCallable<T> implements Callable<T>{ 

 @Override
 public T call() throws Exception {
   System.out.println("开始执行Callable");
   return (T) "测试callable接口";
  }
}
(0)

相关推荐

  • Java数据对象JDO 2.0查询语言的特点

    查询语言的改进是JDO2.0规范中的重要环节,本文从较高的层面阐述JDO2.0所提供的一些新功能.由于JDO2.0规范还未进入公开草案状态,目前还没有任何内容敲定下来,一切都还可能面临变化.不过,JDO2.0将会很快进入最后阶段,而这里提到的查询特性是JDO2.0专家组(译者注:David Jordan就是专家组重要成员)花费时间最多,并且相对来说最为稳定.因此,我有足够理由相信,最终规范与这里的描述将会基本一致. 如果各位读者觉得本文遗漏了某些重要的特性,建议立即到JDO论坛(http://w

  • Java的特点和优点(动力节点整理)

    Java的特点 Java语言是一种优秀的编程语言.它最大的优点就是与平台无关,在Windows 9x.Windows NT.Solaris.Linux.MacOS以及其它平台上,都可以使用相同的代码."一次编写,到处运行"的特点,使其在互联网上广泛采用. 由于Java语言的设计者们十分熟悉C++语言,所以在设计时很好地借鉴了C++语言.可以说,Java语言是一种比C++语言"还面向对象"的一种编程语言.Java语言的语法结构与C++语言的语法结构十分相似,这使得C+

  • JAVA实现单例模式的四种方法和一些特点

    一.饿汉式单例类 复制代码 代码如下: public class Singleton  {      private Singleton(){ } private static Singleton instance = new Singleton(); private static Singleton getInstance(){          return instance;      }  } 特点:饿汉式提前实例化,没有懒汉式中多线程问题,但不管我们是不是调用getInstance()

  • 以实例简介Java中线程池的工作特点

    什么原因使我们不得不使用线程池? 个人认为主要原因是:短时间内需要处理的任务数量很多 使用线程池的好处: 1.减少在创建和销毁线程上所花的时间以及系统资源的开销 2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存 以下是Java自带的几种线程池: 1.newFixedThreadPool  创建一个指定工作线程数量的线程池. 每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中. 2.newCachedThreadPool 创建

  • java中线程池最实用的创建与关闭指南

    目录 前言 线程池创建 只需要执行shutdown就可以优雅关闭 执行shutdownNow关闭的测试 总结 前言 在日常的开发工作当中,线程池往往承载着一个应用中最重要的业务逻辑,因此我们有必要更多地去关注线程池的执行情况,包括异常的处理和分析等. 线程池创建 避免使用Executors创建线程池,主要是避免使用其中的默认实现,那么我们可以自己直接调用ThreadPoolExecutor的构造函数来自己创建线程池.在创建的同时,给BlockQueue指定容量就可以了. private stat

  • 一文带你弄懂Java中线程池的原理

    目录 为什么要用线程池 线程池的原理 ThreadPoolExecutor提供的构造方法 ThreadPoolExecutor的策略 线程池主要的任务处理流程 ThreadPoolExecutor如何做到线程复用的 四种常见的线程池 newCachedThreadPool newFixedThreadPool newSingleThreadExecutor newScheduledThreadPool 小结 在工作中,我们经常使用线程池,但是你真的了解线程池的原理吗?同时,线程池工作原理和底层实

  • Java中线程池自定义实现详解

    目录 前言 线程为什么不能多次调用start方法 线程池到底是如何复用的 前言 最初使用线程池的时候,网上的文章告诉我说线程池可以线程复用,提高线程的创建效率.从此我的脑海中便为线程池打上了一个标签——线程池可以做到线程的复用.但是我总以为线程的复用是指在创建出来的线程可以多次的更换run()方法的内容,来达到线程复用的目的,于是我尝试了一下.同一个线程调用多次,然后使run的内容不一样,但是我发现我错了,一个线程第一次运行是没问题的,当再次调用start方法是会抛出异常(java.lang.I

  • java基于线程池和反射机制实现定时任务完整实例

    本文实例讲述了java基于线程池和反射机制实现定时任务的方法.分享给大家供大家参考,具体如下: 主要包括如下实现类: 1. Main类: 任务执行的入口: 调用main方法,开始加载任务配置并执行任务 package com.yanek.task; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import ja

  • 详解Java并发包中线程池ThreadPoolExecutor

    一.线程池简介 线程池的使用主要是解决两个问题:①当执行大量异步任务的时候线程池能够提供更好的性能,在不使用线程池时候,每当需要执行异步任务的时候直接new一个线程来运行的话,线程的创建和销毁都是需要开销的.而线程池中的线程是可复用的,不需要每次执行异步任务的时候重新创建和销毁线程:②线程池提供一种资源限制和管理的手段,比如可以限制线程的个数,动态的新增线程等等. 在下面的分析中,我们可以看到,线程池使用一个Integer的原子类型变量来记录线程池状态和线程池中的线程数量,通过线程池状态来控制任

  • Java concurrency线程池之线程池原理(一)_动力节点Java学院整理

    ThreadPoolExecutor简介 ThreadPoolExecutor是线程池类.对于线程池,可以通俗的将它理解为"存放一定数量线程的一个线程集合.线程池允许若个线程同时允许,允许同时运行的线程数量就是线程池的容量:当添加的到线程池中的线程超过它的容量时,会有一部分线程阻塞等待.线程池会通过相应的调度策略和拒绝策略,对添加到线程池中的线程进行管理." ThreadPoolExecutor数据结构 ThreadPoolExecutor的数据结构如下图所示: 各个数据在Thread

  • java的线程池框架及线程池的原理

    java 线程池详解 什么是线程池? 提供一组线程资源用来复用线程资源的一个池子 为什么要用线程池? 线程的资源是有限的,当处理一组业务的时候,我们需要不断的创建和销毁线程,大多数情况下,我们需要反复的进行大量的创建和销毁工作,这个动作对于服务器而言,也是很浪费的一种情况,这时候我们可以利用线程池来复用这一部分已经创建过的线程资源,避免不断的创建和销毁的动作. 线程池的原理 创建好固定数量的线程,吧线程先存下来,有任务提交的时候,把资源放到等待队列中,等待线程池中的任务队列不断的去消费处理这个队

  • Java常用线程池原理及使用方法解析

    一.简介 什么是线程池? 池的概念大家也许都有所听闻,池就是相当于一个容器,里面有许许多多的东西你可以即拿即用.java中有线程池.连接池等等.线程池就是在系统启动或者实例化池时创建一些空闲的线程,等待工作调度,执行完任务后,线程并不会立即被销毁,而是重新处于空闲状态,等待下一次调度. 线程池的工作机制? 在线程池的编程模式中,任务提交并不是直接提交给线程,而是提交给池.线程池在拿到任务之后,就会寻找有没有空闲的线程,有则分配给空闲线程执行,暂时没有则会进入等待队列,继续等待空闲线程.如果超出最

  • Java自定义线程池的实现示例

    目录 一.Java语言本身也是多线程,回顾Java创建线程方式如下: 二.JDK线程池工具类. 三.业界知名自定义线程池扩展使用. 一.Java语言本身也是多线程,回顾Java创建线程方式如下: 1.继承Thread类,(Thread类实现Runnable接口),来个类图加深印象. 2.实现Runnable接口实现无返回值.实现run()方法,啥时候run,黑话了. 3.实现Callable接口重写call()+FutureTask获取. public class CustomThread {

随机推荐