关闭

[置顶] 线程池学习总结

1205人阅读 评论(6) 收藏 举报
分类:


   引言

   最近在看项目中的代码的时候,多次看到线程池的身影,于是小编就简单总结了一些关于线程池的知识。

   什么是线程池?为什么要使用它?

   线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。

   线程池的简要工作模型

 

   线程池的工作模型主要两部分组成,一部分是运行Runnable的Thread对象,另一部分就是阻塞队列。由线程池创建的Thread对象其内部的run方法会通过阻塞队列的take方法获取一个Runnable对象,然后执行这个Runnable对象的run方法(即,在Thread的run方法中调用Runnable对象的run方法)。当Runnable对象的run方法执行完毕以后,Thread中的run方法又循环的从阻塞队列中获取下一个Runnable对象继续执行。这样就实现了Thread对象的重复利用,也就减少了创建线程和销毁线程所消耗的资源。当需要向线程池提交任务时会调用阻塞队列的offer方法向队列的尾部添加任务。提交的任务实际上就是是Runnable对象或Callable对象。

   创建线程池的核心类继承关系?

  

   创建线程池需要配置的几个参数?

  corePoolSize
   核心线程数,核心线程会一直存活,即使没有任务需要处理。当线程数小于核心线程数时,即使现有的线程空闲,线程池也会优先创建新线程来处理任务,而不是直接交给现有的线程处理。
核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出。
   maxPoolSize
    当线程数大于或等于核心线程,且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolSize。如果线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常。
   keepAliveTime
    当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0。
   allowCoreThreadTimeout
     是否允许核心线程空闲退出,默认值为false。
   queueCapacity
    任务队列容量。从maxPoolSize的描述上可以看出,任务队列的容量会影响到线程的变化,因此任务队列的长度也需要恰当的设置。

   线程池的主要处理流程?

   线程池的种类

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

   

package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
 public static void main(String[] args) {
  ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
  for (int i = 0; i < 10; i++) {
   final int index = i;
   fixedThreadPool.execute(new Runnable() {
    public void run() {
     try {
      System.out.println(index);
      Thread.sleep(2000);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
   });
  }
 }
}
   newCachedThreadPool创建一个可缓存的线程池。这种类型的线程池特点是: 
    1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。 
    2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。

package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
 public static void main(String[] args) {
  ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
  for (int i = 0; i < 10; i++) {
   final int index = i;
   try {
    Thread.sleep(index * 1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   cachedThreadPool.execute(new Runnable() {
    public void run() {
     System.out.println(index);
    }
   });
  }
 }
}
   newScheduleThreadPool创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。

   

package test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
 public static void main(String[] args) {
  ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
  scheduledThreadPool.schedule(new Runnable() {
   public void run() {
    System.out.println("delay 3 seconds");
   }
  }, 3, TimeUnit.SECONDS);
 }
}

   newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的 。

   

package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
 public static void main(String[] args) {
  ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
  for (int i = 0; i < 10; i++) {
   final int index = i;
   singleThreadExecutor.execute(new Runnable() {
    public void run() {
     try {
      System.out.println(index);
      Thread.sleep(2000);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
   });
  }
 }
}

   总结: 

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

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

   小结

   在我们项目中正确使用合适的线程池可以很大程度上提高我们系统的性能,在我们选择线程池的种类的时候,需要我们了解这些线程池的工作原理和一些优劣,小编在本篇博客中总结了一些核心的东西,希望对您有帮助!

 


2
0
查看评论

muduo网络库源码学习————线程池实现

muduo库里面的线程池是固定线程池,即创建的线程池里面的线程个数是一定的,不是动态的。线程池里面一般要包含线程队列还有任务队列,外部程序将任务存放到线程池的任务队列中,线程池中的线程队列执行任务,也是一种生产者和消费者模型。muduo库中的线程池源码如下: 线程池头文件ThreadPool.h/...
  • L979951191
  • L979951191
  • 2015-08-29 18:17
  • 981

十月学习总结 大学的第一个月

来到烟台两个月了,而真
  • zp___waj
  • zp___waj
  • 2014-11-03 11:34
  • 2961

2017年度学习总结

2017上半年,移动平台游戏开发基础,学习了灵活的JavaScript语言,也做了几个像模像样的游戏,JQuary库和其他库的的引用也很受益。想想原来,每种框架都想入门试试,可忽略了开发者最基本的底层基础。CSDN上记得大牛说过,“框架也是人写的,哪天框架不在了,你也就不在了”大概是这个意思。我原来...
  • Prototype___
  • Prototype___
  • 2017-12-31 07:09
  • 366

JAVA 学习 自我总结

学习总结: 孔子曰学而时习之 不亦悦乎 。学习了新的东西,一定要及时练习和总结,并多次回想记忆,这样才能将知识记忆的牢固; 之前我学习东西只知道贪多,想一口吃一个胖子;但是每次都是事倍功半,这样又会挫败了我的自信让我更加没有信心去学习。 其实仔细想一想,学不好的原因,无外乎,以下几点: 第一...
  • u010582345
  • u010582345
  • 2016-04-08 23:58
  • 424

Hibernate学习总结(一)

1、什么是Hibernate Hibernate是轻量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架(ORM,对象关系映射 Object Relationship mapper) ORM 就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作 轻量级...
  • u012750846
  • u012750846
  • 2015-09-07 15:36
  • 803

程序员的学习总结

数据结构+算法 网络编程 分布式框架
  • very_loong
  • very_loong
  • 2017-09-16 10:44
  • 250

C#学习总结(一)

(一)基本概念 .NET框架,CLR和C#之间的关系。 .NET是一个独立发布的软件包,包括CLR,类库 和相关语言编译器 C#代码 经编译后 在CLR环境运行  不同.NET版本的比较: .NET3/3.5只是扩展了WF、WPF、...
  • doupei2006
  • doupei2006
  • 2012-09-30 18:09
  • 1417

Linux学习总结(七)

Linux学习总结(七)多线程异步管理——信号线程并没有自己完全独立的异步信号管理机制,因此需要依赖于所在的进程,每个线程仅仅只能管理自己私有的信号屏蔽集合。因此信号操作时具有一下操作 (1)每个线程可以向其他线程发送信号,pthread_kill()函数用来完成这一操作,接受者为对应的线程 (2)...
  • jkhero
  • jkhero
  • 2017-06-04 19:54
  • 544

node.js学习总结

NodeJS介绍 1.概述:       Node.js是基于Chrome JavaScript运行时建立的一个平台,实际上它是对Google Chrome V8引擎 进行了封装,它主要用于创建快速的、可扩展的网络应用。Node.js采用事件驱动和非阻塞I/O模型...
  • bcbobo21cn
  • bcbobo21cn
  • 2016-04-11 08:44
  • 1954

Android个人学习小结2016.4

以下内容仅为个人初学Android小结及生活,不太适合其他人看。1、 无论在哪里,在做什么,只要坚持学习、探索、创造价值,其他的东西自然都会来的。2、微信-我的-钱包-城市服务-社保查询,可以查个人社保情况!!3、android:layout_alignParentRight=”true” 居右显示...
  • forgot2015
  • forgot2015
  • 2016-05-31 00:07
  • 959
    个人资料
    • 访问:563391次
    • 积分:18482
    • 等级:
    • 排名:第599名
    • 原创:274篇
    • 转载:20篇
    • 译文:0篇
    • 评论:5683条
    和我交谈
    点击这里给我发消息 点击这里给我发消息
    时间你好?
    博客专栏
    最新评论