`
youyu4
  • 浏览: 440083 次
社区版块
存档分类
最新评论

Java多线程之线程池概述

 
阅读更多

Java多线程之线程池

 

适用情况

 

  • 单个处理时间比较短
  • 将要处理的任务量比较大

 

 

好处

 

  • 线程重复使用
  • 减少多次创建和注销线程的开销

 

 

工作模型

 


 

    1. 线程池的工作模型主要两部分组成,一部分是运行Runnable的Thread对象,另一部分就是阻塞队列。

 

    2. 由线程池创建的Thread对象其内部的run方法会通过阻塞队列的take方法获取一个Runnable对象,然后执行这个Runnable对象的run方法(即,在Thread的run方法中调用Runnable对象的run方法)。

 

    3. 当Runnable对象的run方法执行完毕以后,Thread中的run方法又循环的从阻塞队列中获取下一个Runnable对象继续执行。

 

    4. 当需要向线程池提交任务时会调用阻塞队列的offer方法向队列的尾部添加任务。提交的任务实际上就是是Runnable对象或Callable对象。

 

 

 

 

线程池工作流程

  

 

  1. 核心线程数,在创建线程池的时候还没有初始化
  2. 提交任务时,先判断核心线程数是否已经到达上限,如果不是就创建线程
  3. 如果工作线程数大于核心线程数,且任务队列未满,就进入任务队列
  4. 如果工作线程数大于核心线程数,且任务队列已满,那看工作线程数是否小于最大线程数,如果小于则创建线程
  5. 如果工作线程等于最大线程数,就会通过Handler所指定的策略来执行任务

上面的工作流程是根据ThreadPoolExecutor而言的,其实线程池的工作流程还要根据选择的线程池种类而定。



 

 

 

参数配置

 

corePoolSize:核心线程数

 

  • 核心线程会一直存活,及时没有任务需要执行
  • 当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理
  • 设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭

 

queueCapacity:任务队列容量(阻塞队列)

 

  • 当核心线程数达到最大时,新任务会放在队列中排队等待执行

 

maxPoolSize:最大线程数

 

  • 当线程数>=corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务
  • 当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常

 

keepAliveTime:线程空闲时间

 

  • 当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize
  • 如果allowCoreThreadTimeout=true,则会直到线程数量=0

 

allowCoreThreadTimeout:允许核心线程超时

 

  • 这个值只设置true,false

 

rejectedExecutionHandler:任务拒绝处理器

 

下面两种情况会拒绝处理任务:

 

  • 当线程数已经达到maxPoolSize,且队列已满,会拒绝新任务
  • 当线程池被调用shutdown()后,会等待线程池里的任务执行完毕,再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务

几种拒绝任务的处理方式:

 

  • AbortPolicy(默认) 丢弃任务,抛运行时异常
  • CallerRunsPolicy 执行任务
  • DiscardPolicy 忽视,什么都不会发生
  • DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务

 

 

 

 

线程池种类

 

  • 固定数量线程池
  • 单一线程池:只有一个线程
  • 缓存线程池:线程池中的线程数量不固定,会根据需求改变
  • 计划任务调度线程池:用于执行计划,比如每五分钟执行一次
  • ThreadPoolExecutor

 

 

newFixedThreadPool

 

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

 

优缺点 

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

 

代码

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();
     }
    }
   });
  }
 }
}

 

 

 

newSingleThreadExecutor

 

创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。

 

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

 

代码

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();
     }
    }
   });
  }
 }
}

 

 

 

newCachedThreadPool

 

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

 

优缺点

  • 工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
  • 如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
  • 在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。

代码

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

 

创建一个定长的线程池,而且支持定时的以及周期性的任务执行。

 

延迟3秒执行,延迟执行示例代码如下:

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);
 }
}

 

表示延迟1秒后每3秒执行一次,定期执行示例代码如下:

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.scheduleAtFixedRate(new Runnable() {
   public void run() {
    System.out.println("delay 1 seconds, and excute every 3 seconds");
   }
  }, 1, 3, TimeUnit.SECONDS);
 }
}

 

 

 

ThreadPoolExecutor

 

这是我们最常用的线程池,是线程池接口ExecutorService的实现类,其实上面的4中线程池都是由这个实现类来实现。

 

代码

public class DiscardPolicyDemo {  

    private static final int THREADS_SIZE = 1;  
    private static final int CAPACITY = 1;  

    public static void main(String[] args) throws Exception {  

        // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。  
        ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CAPACITY));  
        // 设置线程池的拒绝策略为"丢弃"  
        pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());  

        // 新建10个任务,并将它们添加到线程池中。  
        for (int i = 0; i < 10; i++) {  
            Runnable myrun = new MyRunnable("task-"+i);  
            pool.execute(myrun);  
        }  
        // 关闭线程池  
        pool.shutdown();  
    }  
}

 

 

 

线程池拒绝策略

 

  • AbortPolicy(默认):如不能接收任务,抛异常
  • CallerRunsPolicy:~~~~~~~~,让调用的线程去完成
  • DiscardOldestPolicy:~~~~~~,则丢弃最老一个任务,由一个队列来维护
  • DiscardPolicy:~~~~~~~~~~~,丢弃任务

设置线程池拒绝策略

// 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。  
ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CAPACITY));  
// 设置线程池的拒绝策略为"丢弃"  
pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());

  

 

 

线程池优化需要考虑的因数

  • 并发数
  • 单次请求的执行时间

 

 

线程池初始化

  • 默认新创建线程池中没有线程,有任务后才创建
  • prestartCoreThread()初始化一个核心线程
  • prestartAllCoreThread()初始化所有核心线程

 

 

线程池关闭

  • shutdown(),等任务执行完再终止,不接受新任务
  • shutdownNow(),马上终止,打断正在执行的任务,清空缓存队列,返回未执行的任务

 

  • 大小: 70.7 KB
  • 大小: 132 KB
  • 大小: 70.3 KB
  • 大小: 72.8 KB
分享到:
评论

相关推荐

    java多线程加队列上传文件_后台处理

    ### Java多线程加队列上传文件_后台处理 #### 概述 本文将详细介绍一个基于Java实现的多线程文件上传系统,并结合队列管理技术来优化后台处理流程。该系统通过创建多个线程来并行处理客户端的文件上传请求,同时...

    基于线程池的Java多线程应用技术.pdf

    基于线程池的Java多线程应用技术 概述: Java多线程机制是Java编程语言中的一种重要机制,它通过多线程技术提高了任务的执行效率。线程池技术是Java多线程机制中的一个重要组成部分,它能够有效地满足同类的、独立...

    java 多线程设计模式 进程详解

    《JAVA多线程设计模式》PDF 下载 《Java线程 高清晰中文第二版》中文第二版(PDF) 前言 第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口...

    Java多线程之基础篇(一).docx

    Java多线程的使用涉及线程安全、线程通信、线程池等多个方面,需要深入理解并熟练掌握,才能在实际开发中有效地利用多线程优化程序性能。通过合理地设计和使用线程,开发者可以构建出高效、健壮的并发应用程序。

    java多线程的两种实现

    以上是对Java多线程基础知识的概述,学习和理解这些概念对于开发高效的并发应用程序至关重要。在实际开发中,应根据需求选择合适的线程实现方式,并熟练掌握线程同步和通信机制,确保程序的正确性和性能。

    java多线程作业.docx

    #### 一、Java多线程概述 Java作为一种现代编程语言,内置了对多线程的支持。多线程允许应用程序同时处理多个任务,从而提高程序的响应性和整体性能。在多线程环境中,一个程序可以包含多个线程,每个线程都是独立...

    Java 多线程学习总结归纳(附代码)

    Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,从而提升系统效率。在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。下面是对Java多线程学习的详细解析。 1. **多线程概述*...

    基于Java的多线程网络爬虫设计与实现.txt

    ### 基于Java的多线程网络爬虫设计与实现 #### 概述 本文档探讨了在Java环境下设计与实现多线程网络爬虫的技术细节与实践方法。网络爬虫(Web Crawler),是一种自动抓取互联网上网页信息的程序或自动化脚本,其...

    java大批量导入excel,多线程加分片处理的dome

    ### Java大批量导入Excel:多线程加分片处理详解 #### 概述 在实际工作中,经常需要批量处理大量的Excel数据。当面对成千上万甚至百万级别的数据时,简单的单线程处理方式往往无法满足效率的需求。为了解决这个...

    基于Java多线程机制的探析

    #### Java多线程概述 Java的多线程机制是其核心特性之一,它允许程序员在同一个应用程序中并发地执行多个任务,极大地提升了程序的响应能力和整体性能。多线程通过允许多个指令流(即线程)同时运行,从而提高程序...

    Java多线程基础-01、数组概述.rar

    本资料“Java多线程基础-01、数组概述”将带你入门Java的多线程世界,并结合数组这一基本数据结构进行讲解。 首先,我们需要理解什么是线程。线程是操作系统分配CPU时间的基本单位,一个进程可以有多个线程,它们...

    自定义实现Java线程池

    线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池可以有效控制运行的线程数量,如果线程数量超过了最大数量,超出数量的线程排队等候;另一方面,如果线程数量...

    java多线程编程总结

    #### 一、Java多线程概述 Java多线程是Java编程语言中不可或缺的一部分,它允许程序同时处理多个任务,从而显著提高应用程序的性能和响应速度。Java5之前的版本虽然支持多线程,但在语言层面的支持较为有限,这使得...

    Java多线程编程

    ### Java多线程编程知识点详解 #### 一、线程基础概述 - **定义与特点:** - **线程**是一种比进程更细粒度的执行单元,它允许在一个进程中并发执行多个任务。 - **轻量级进程**:线程有时被称为轻量级进程,...

    java多线程设计模式详解

    以上是部分Java多线程设计模式的概述,每个模式都有其适用场景和优缺点。实际开发中,开发者应根据需求选择合适的模式,结合 synchronized 关键字、volatile 变量、原子类(Atomic*)等并发控制工具,保证代码的正确...

    Java多线程文章系列.pdf

    #### 十一、实战Java多线程编程精要之高级支持 - **线程组**: - 用于管理和控制一组线程。 - **线程间发信**: - 实现线程间的通信。 - **屏蔽同步**: - 采用特定技术减少同步的使用。 - **守护线程**: - 守护...

    基于Java多线程与线程安全实践(源码+使用文档)

    基于Java多线程与线程安全实践是一个旨在展示如何在Java环境中高效、安全地使用多线程技术的系统。该系统通过结合源码示例和详细的使用文档,帮助开发者深入理解并实践线程安全的概念。 主要功能 线程安全示例:...

    多线程面试题

    以上是对“多线程面试题”这一主题的简要概述,实际面试中可能会涉及到更深层次的问题,如并发模型、线程池的优化策略、线程安全的实现原理等。深入理解和熟练运用这些知识点,将有助于你在面试中脱颖而出,解决实际...

Global site tag (gtag.js) - Google Analytics