java所提供的线程池有几种之线程池总结

今天给大家带来一个关于java线程池的资料,主要是因为在早些时候去面试的时候就被问到了线程池的问题,回答的不尽人意,今天突然有人问我一个同样的问题,我觉的我还是总结一下,看起来也方便。

  Java提供的几种线程池线程池,顾名思义,放线程的池子嘛,这个池子可以存放多少线程取决于你自己采用什么样的线程池,你的硬件资源,以及并发线程的数量。JDK提供了下面的四种线程池:

  固定线程数的线程池#

  最简单的

  在Java中创建一个线程池,这很简单,只需要两行代码。

  

  CopyExecutorService executor = Executor.newFixedTreadPool(6);//固定线程是6
  //线程一般设置成processor核心数的倍数,因为我这台机器是6核的,所以设成6。这也是充分利用硬件嘛

  //执行线程任务

  executor.execute(new Runnable(){

  @Override

  public void run(){

  //do nothing

  }

  })

  executor.shutdown();

  Executor是Java并发包中提供的,用来创造不同类型的线程池。

  Attention

  但是在多人合作或者是一些部署上线的项目里,是不允许去使用这种方法的,因为它是有性能隐患的。

  Executors在创建线程池的时候,用的是new LinkedBlockingQueue(),它这个队列本身是无边界的,但是线程是固定数量的。这就意味着,在程序运行的过程中,最多会有N个线程在处于活动状态。每次有新的任务来就会等待,直到有线程处于空闲状态。所有的线程都会处于线程池里里面,直到shutdown()的执行。

  它的问题就在于来者不拒,只要有任务来,你就进队列等着。在入队列和出队列用的并不是同一个lock,在多processor的机器上,是可以做到真正意义上的并行的。拿经典的生产者和消费者来举例子,在同一个时间点,有的在消费,有的在生产。

  这种线程池不会销毁线程,不会拒绝任务,固定线程数。所以如果不停的加入任务,会导致很糟糕的内存占用,老年代可能会被占满。

  稍复杂的(可以延时执行,也可以执行带返回值的任务)

  

Copypublic static void main(String[] args) throws InterruptedException, ExecutionException {

  TestThread testThread = new TestThread();

  System.out.println(testThread.processors);

  ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(6);

  FutureTask futureTask = new FutureTask<>(new Callable() {

  @Override

  public String call() throws Exception {

  return Thread.currentThread().getName();

  }

  });

  scheduledExecutorService.submit(futureTask);

  //获取返回值

  String result = futureTask.get();

  System.out.println("result :"+result);

  //执行延时任务

  scheduledExecutorService.schedule(new Runnable() {

  @Override

  public void run() {

  System.out.println(Thread.currentThread().getName()+": bomb!");

  }

  },3L,TimeUnit.SECONDS);

  }

  Output:

  result :pool-1-thread-1

  pool-1-thread-1: bomb!

  缓存的线程池#

  核心池大小为0,线程池最大线程数目为最大整型,这意味着所有的任务一提交就会wait。当线程池中的线程有60s没有执行任务就会被Kill,阻塞队列为SynchronousQueue。SynchronousQueue的take操作需要put操作等待,put操作需要take操作等待,否则会阻塞(线程池的阻塞队列不能存储,所以当目前线程处理忙碌状态时,会开辟新的线程来处理请求**),线程进入wait set。

  总结一下这是一个可以无限扩大的线程池;适合处理执行时间比较小的任务;线程空闲时间超过60s就会被Kill,所以长时间处于空闲状态的时候,这种线程池几乎不占用资源,因为它压根没有线程在里面;阻塞队列没有存储空间,只要请求到来,就必须找到一条空闲线程去处理这个请求,找不到则在线程池新开辟一条线程。

  如果主线程提交任务的速度远远大于CachedThreadPool的处理速度,则CachedThreadPool会不断地创建新线程来执行任务,这样有可能会导致系统耗尽CPU和内存资源,所以在使用该线程池时,要注意控制并发的任务数。如果是一个不断增长的任务需求,很容易就会到性能瓶颈,它会不停的创建新的线程。

 

 Copy ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

  for (int i = 0; i < 10; i++) {

  cachedThreadPool.execute(new Runnable() {

  @Override

  public void run() {

  System.out.println(Thread.currentThread().getName());

  }

  });

  }

  cachedThreadPool.shutdown();

  Output:

 

 pool-1-thread-2

  pool-1-thread-6

  pool-1-thread-1

  pool-1-thread-7

  pool-1-thread-8

  pool-1-thread-3

  pool-1-thread-5

  pool-1-thread-9

  pool-1-thread-4

  pool-1-thread-10

  单个线程的线程池#

  SingleThreadExecutor 是使用单个worker线程的Executor。只有一种情况会有新的线程加入线程池,那就是原有的线程运行时有抛出异常,这时就会有创建的新的线程来替代它的工作。

  拿生产者消费者模型来说的话,这就是一个单一消费者的模型。

  (ps.一般可以用来做一些日志记录

  

Copy public static void main(String[] args) {

  // 永远是一条线程

  ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

  for (int i = 0; i < 10; i++) {

  final int j = i;

  singleThreadPool.execute(new Runnable() {

  @Override

  public void run() {

  System.out.println(Thread.currentThread().getName() + ":" + j);

  }

  });

  }

  singleThreadPool.shutdown();

  }

  Output:

  

pool-1-thread-1:0

  pool-1-thread-1:1

  pool-1-thread-1:2

  pool-1-thread-1:3

  pool-1-thread-1:4

  pool-1-thread-1:5

  pool-1-thread-1:6

  pool-1-thread-1:7

  pool-1-thread-1:8

  pool-1-thread-1:9

线程池给大家说完了,最后给大家一些java方面的小资料,希望可以帮到大家

面向高级对象
http://www.makeru.com.cn/live/detail/251.html?s=45051

java中读取配置文件的几种方式
http://www.makeru.com.cn/live/1394_481.html?s=45051

使用java发送邮件
http://www.makeru.com.cn/live/1394_482.html?s=45051
java之网络聊天
http://www.makeru.com.cn/live/1394_349.html?s=45051

原文地址:https://www.cnblogs.com/QianD/p/11244804.html

时间: 2024-10-06 13:00:56

java所提供的线程池有几种之线程池总结的相关文章

java线程池和五种常用线程池的策略使用与解析

java线程池和五种常用线程池策略使用与解析 一.线程池 关于为什么要使用线程池久不赘述了,首先看一下java中作为线程池Executor底层实现类的ThredPoolExecutor的构造函数 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory th

java线程池与五种常用线程池策略使用与解析

背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQueue详解 首先看一下新任务进入时线程池的执行策略: 如果运行的线程少于corePoolSize,则 Executor始终首选添加新的线程,而不进行排队.(如果当前运行的线程小于corePoolSize,则任务根本不会存入queue中,而是直接运行) 如果运行的线程大于等于 corePoolSize

线程同步机制(二)-- 线程同步辅助类

我们在线程同步机制(一)--Synchronized和Lock简要介绍中学习了同步和临界区的概念,并且讨论了多个并发任务共享一个资源时的同步情况.访问共享资源的代码块叫临界区. 我们在线程同步机制(一)--Synchronized和Lock简要介绍中学习了一下内容: synchronized关键字 Lock接口及其实现类,如ReentrantLock,ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock 本章我们将学习如

Java默认提供的线程池

Java的线程池都是通过ThreadPoolExecutor来构建. public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSi

java多线程(三)-Executors实现的几种线程池以及Callable

从java5开始,类库中引入了很多新的管理调度线程的API,最常用的就是Executor(执行器)框架.Executor帮助程序员管理Thread对象,简化了并发编程,它其实就是在 提供了一个中间层,方便程序员管理异步任务的执行,而又不用显式的管理线程的生命周期. Executor采用了线程池实现,也更节约开销,因为是我们启动新线程的首选方法. 示例代码:src/thread_runnable/CachedThreadPool.java 1 public class CachedThreadPo

JAVA并发API源码解析:并发数据结构、线程、线程池及其应用

首先介绍Callable这个接口,它仅包含一个方法call,它是类似于Runnable接口,是Future并发设计模式下实际的任务执行单元,它能返回一个对象.我们可以实现它的子类并使用Future对象来提交它.现在我们再来看看Futrue,futrue提供了get方法来返回计算结果,cancel来中断任务.Future还会进一步被封装成FutureTask等任务类,这些任务会被提交给ExecutorService,ExecutorService(ThreadPoolExecutor是它的子类)是

Java线程池的几种实现 及 常见问题讲解

工作中,经常会涉及到线程.比如有些任务,经常会交与线程去异步执行.抑或服务端程序为每个请求单独建立一个线程处理任务.线程之外的,比如我们用的数据库连接.这些创建销毁或者打开关闭的操作,非常影响系统性能.所以,“池”的用处就凸显出来了. 1. 为什么要使用线程池 在3.6.1节介绍的实现方式中,对每个客户都分配一个新的工作线程.当工作线程与客户通信结束,这个线程就被销毁.这种实现方式有以下不足之处: 服务器创建和销毁工作的开销( 包括所花费的时间和系统资源 )很大.这一项不用解释,可以去查下"线程

Java线程池的四种创建方式

Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保

Java线程池主线程等待子线程执行完成

今天讨论一个入门级的话题, 不然没东西更新对不起空间和域名~~ 工作总往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线程的流程,  往往需要让主线程指定后, 等待子线程的完成. 这里有几种方式. 站在 主线程的角度, 我们可以分为主动式和被动式. 主动式指主线主动去检测某个标志位, 判断子线程是否已经完成. 被动式指主线程被动的等待子线程的结束, 很明