目录

一.介绍

二.ThreadPoolExecutor

  2.1 认识ThreadPoolExecutor

  2.2 ThreadPoolExecutor的构造方法列表

  2.3 任务队列分类

  2.4 线程工厂

  2.5 拒绝策略

三.使用Executors快速创建线程池

一.介绍

  本文主要介绍线程池的创建、线程任务队列分类以及线程池的扩展相关内容,只包含比较基础的知识,可以用来复习知识。

二.ThreadPoolExecutor

2.1 认识ThreadPoolExecutor

  ThreadPoolExecutor,可以理解为ThreadPool+Executor(线程池+执行器),执行器会使用线程池中的线程来处理提交的任务,可以看下面的继承关系图:

  

2.2 ThreadPoolExecutor的构造方法列表

  创建线程池,就是创建ThreadPoolExecutor实例对象,需要注意的是ThreadPoolExecutor有多个构造方法,如下所示:

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

  corePoolSize:核心线程数(作用相当于一个门限值,看后面的介绍就知道了)

  maximumPoolSize:线程池中线程的最大数量;

keepAliveTime,TimeUnit:当线程池中的线程数量超过corePoolSize后,多余的空闲线程存活的时间,也就是超过corePoolSize的空闲线程在多长时间后会被销毁;

  workQueue:任务队列,用来保存已经提交但是并没有被执行的任务;

  threadFactory:线程池中线程的创建工厂(默认使用Executors.DefaultThreadFactory);

  handler:拒绝策略,当任务来不及被处理时被拒绝的处理操作;

2.3 任务队列分类

SynchronousQueue(同步队列):

1.当前线程池中的线程数量没有达到最大线程数,当任务被提交时:

a.如果有空闲线程,则让空闲线程来处理任务;

b.如果没有空闲线程,那么就会创建新的线程来处理任务;

2.当前线程池中的线程数量已经达到最大线程数,当任务被提交时:

a.如果有空闲线程,则让空闲线程来处理任务;

b.如果没有空闲线程,那么就会执行拒绝策略;这个时候,如果希望任务能被提交,那么就必须等待一个线程执行完成,空出一个空闲线程,所以“每一个插入操作,都必须等待一个删除操作”。

3.综上,SynchronousQueue没有容量的概念,只有maximumPoolSize起着“容量”的作用。

ArrayBlockingQueue(有界队列)

1.创建ArrayBlockingQueue必须指定容量,也就是队列的最大长度;

2.当有新任务提交的时候,会有下面几种情况:

a.如果线程池中线程的数量小于corePoolSize,那么就会创建新线程来处理任务(如果有空闲线程,则让空闲线程处理);

b.如果线程池中的线程数量达到corePoolSize,那么就会将任务提交到任务队列;

c.如果任务队列已经满了,那么就会在线程池中数量不超过maximumPoolSize的前提下,创建线程来处理提交的任务;

d.如果任务队列已满,且线程池中线程数量已经达到maximumPoolSize数量,那么就会执行拒绝策略;

3.综上,使用ArrayBlockingQueue,线程池只有当任务队列满了之后才会创建超过corePoolSize的线程进行处理任务,在这之前,线程池中的最多保持corePoolSize个线程;

LinkedBlockingQueue(无界队列)

1.创建LinkedBlockingQueue时可以指定容量,也可以不指定容量;

2.对于不指定容量的LinkedBlockingQueue,当有任务提交的时候:

a.如果线程池中的线程数量小于corePoolSize,那么就会创建新线程来执行任务(如果有空闲线程,则让空闲线程处理);

b.如果线程池中的线程数量达到corePoolSize后,如果有空闲线程,那么就让空闲线程来执行任务,如果没有空闲线程,那么就会将任务提交到任务队列,而不会创建新线程来执行任务;

3.综上,使用LinkedBlockingQueue时,线程数量达到corePoolSize后,就不会再创建新线程了,后面的任务都会直接进入任务队列,如此的话,如果提交的任务很多,则会造成系统资源枯竭;

4.如果担心任务无线提交,则可以创建LinkedBlockingQueue时指定队列容量,超过队列容量后,再往队列中提交任务,则会触发拒绝策略;

PropertyBlockingQueue(优先队列)

为任务设置优先级,提交到任务队列后,会根据优先级进行处理任务,而不是按照先到先服务的算法进行处理(SynchronousQueue、ArrayBlockingQueue、LinkedBlockingQueue中的任务都是按照FIFO算法处理)。

2.4 线程工厂

  熟悉设计模式的话,就知道XX工厂,就是用来创建XX的,所以ThreadFactory就是用来创建线程的,一般来说,我们直接使用默认的线程工厂即可,也就是Executors.DefaultThreadFactory;

  但是有时候我们需要对线程的创建做一些扩展,就可以通过对创建自己的线程工厂来实现,可以参考这篇博客,利用线程自定义线程工厂来对线程池中的线程进行命名的方式:Java的每个Thread都希望拥有自己的名称

  注意,可以通过继承ThreadPoolFactory来扩展线程池。

2.5 拒绝策略

  当任务不能提交到任务队列时,执行的操作,称为拒绝策略,只需要实现RejectedExecutionHandler接口接口:

package cn.ganlixin.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor; @Slf4j
public class MyRejectedExecutionHandler implements RejectedExecutionHandler { /**
* 拒绝策略处理逻辑
*
* @param task 提交到任务队列被拒绝的任务
* @param executor 执行任务的执行器(线程池)
*/
@Override
public void rejectedExecution(Runnable task, ThreadPoolExecutor executor) {
// 在这里定义逻辑,我这里只是输出一串文字
log.error("提交任务被拒绝");
}
}

  

  使用示例:

package cn.ganlixin.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class TestThread { public static void main(String[] args) throws InterruptedException { Runnable runnable = () -> {
Thread thread = Thread.currentThread();
String name = thread.getName();
log.info("thread {} running", name); try {
TimeUnit.SECONDS.sleep(5); // 休眠5秒
} catch (InterruptedException ignored) {
}
}; int corePoolSize = 2;
int maximumPoolSize = 4; // 最多4个线程
int keepAliveSecond = 5;
ExecutorService executorService = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveSecond, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2), // 任务队列容量为2
Executors.defaultThreadFactory(),
new MyRejectedExecutionHandler()); // 提交8个任务,因为线程池最多有4线程,再加上2个任务队列的任务,所以有2个任务会被拒绝
for (int i = 0; i < 8; i++) {
executorService.submit(runnable);
} // 输出如下:
// thread pool-2-thread-3 running
// thread pool-2-thread-2 running
// thread pool-2-thread-4 running
// thread pool-2-thread-1 running
// 提交任务被拒绝
// 提交任务被拒绝
// thread pool-2-thread-4 running
// thread pool-2-thread-2 running Thread.currentThread().join();
}
}

  

三.使用Executors快速创建线程池

  可以利用Executors类的各个静态方法来创建线程池,创建的线程池特点从名称上就可以看出来,需要注意的这些静态方法内部其实也是ThreadPoolFactory实例对象,也就是线程池,只不过根据不同的类型设置了不同的参数。

  

  

Java Web的简单项目部署的更多相关文章

  1. atitit.研发管理--标准化流程总结---java开发环境与项目部署环境的搭建工具包总结

    atitit.研发管理--标准化流程总结---java开发环境与项目部署环境的搭建工具包总结 1. ide系列(只开发环境需要,但部署环境也做好放上,很有用) 1 2. web服务器+sdk+网站程序 ...

  2. 用于 Visual Studio 和 ASP.NET 的 Web 应用程序项目部署常见问题

    https://msdn.microsoft.com/zh-cn/library/ee942158(v=vs.110).aspx#can_i_exclude_specific_files_or_fol ...

  3. Linux Ubuntu从零开始部署web环境及项目 -----部署项目 (三)

    上一篇讲了如何在linux搭建web环境,这边将如何部署项目. 1,打包项目包 2,上传项目包 将.war项目包通过xftp上传到tomcat目录wabapps目录下 3,启动项目 通过xshell命 ...

  4. Java Web开发中用Tomcat部署项目的三种方法

    第一种方法:在tomcat中的conf目录中,在server.xml中的,<host/>节点中添加: <Context path="/hello" docBase ...

  5. 天坑 之 java web servlet+jsp项目 配置后 404 (MyEclipse转eclipse)

    最近搞一个自己的博客系统玩,用了servlet+jsp,结果发现了两个大问题: 1.无法 Export 出 WAR文件: 2.生成WAR,放置到TOMCAT的 webapps目录后,http://lo ...

  6. Java web会话简单应用

    Java会话主要分为两块:Cookie和HttpSessionCookie技术:会话数据保存在浏览器客户端.Session技术:会话数据保存在服务器端.一.下面介绍一下Cookie的应用1. Cook ...

  7. Servlet监听器与Timer定时器配合实现JAVA WEB应用简单自动作业

    在web应用中,有时候客户需要一些定时程序,不需要客户自己去操作,而是由应用程序自行触发执行某些操作.这个时候监听与定时器的配合使用就基本可以实现这个需求了. 1.创建一个监听的SERVELET,这个 ...

  8. java web程序中项目名的更改(http://localhost:8080/)后面的名字

    在MyEclipse中的Web项目,如果想另换名称(Context-root)进行发布,可以在项目的属性中进行设置.设置路径如下: 右击项目XX(或选中项目XX,按快捷键Alt+Enter), 打开项 ...

  9. 王立平--java se的简单项目创建以及具体解释

    创建项目的简单步骤: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzQyNTUyNw==/font/5a6L5L2T/fontsize/400/ ...

随机推荐

  1. 小白都会超详细--ELK日志管理平台搭建教程

    目录 一.介绍 二.安装JDK 三.安装Elasticsearch 四.安装Logstash 五.安装Kibana 六.Kibana简单使用 系统环境:CentOS Linux release 7.4 ...

  2. .NET Core 的缓存篇之MemoryCache

    前言 对于缓存我们都已经很熟悉了,缓存分为很多种,浏览器缓存.试图缓存.服务器缓存.数据库缓存等等一些,那今天我们先介绍一下视图缓存和MemoryCache内存缓存的概念和用法: 视图缓存 在老的版本 ...

  3. Vue2.0源码阅读笔记(二):响应式原理

      Vue是数据驱动的框架,在修改数据时,视图会进行更新.数据响应式系统使得状态管理变的简单直接,在开发过程中减少与DOM元素的接触.而深入学习其中的原理十分有必要,能够回避一些常见的问题,使开发变的 ...

  4. javascript 作用域链及闭包,AO,VO,执行环境

    下面的文章内容会根据理解程度不断修正. js变量作用域: 定义:变量在它申明的函数体以及函数体内嵌套的任意函数体内有定义. function AA(){ var bb='我是AA内部变量'; func ...

  5. 论文学习-系统评估卷积神经网络各项超参数设计的影响-Systematic evaluation of CNN advances on the ImageNet

    博客:blog.shinelee.me | 博客园 | CSDN 写在前面 论文状态:Published in CVIU Volume 161 Issue C, August 2017 论文地址:ht ...

  6. javascript小记一则:今天在写VS2005——.NET程序时,写的一个JS图片示例案例

    源码如下,如遇调试问题,可以找我解决: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  7. MySQL 笔记整理(14) --count(*)这么慢,我该怎么办?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 14) --count(*)这么慢,我该怎么办? 有时你会发现,随着系统 ...

  8. chrome主页被篡改为hao123 win10系统

    应该是开了个从流氓网站下的蓝灯,然后发现主页被篡改 尝试chrome设置修改无效,应该是快捷方式被改了 系统 win10 1.打开对应的下面两个地址,找到chrome的快捷方式,右键属性 C:\Use ...

  9. foreach(Element elem in selections.Elements)无法实现

    因为版本问题 原:foreach(Element elem in selections.Elements){ } 现: ElementSet selections = new ElementSet() ...

  10. 第五章:shiro密码加密

    在涉及到密码存储问题上,应该加密/生成密码摘要存储,而不是存储明文密码.比如之前的600w csdn账号泄露对用户可能造成很大损失,因此应加密/生成不可逆的摘要方式存储. 5.1 编码/解码 Shir ...