线程池

并发编程之线程池ThreadPoolExecutor

不打扰是莪最后的温柔 提交于 2020-02-28 02:16:59
前言 在我们平时自己写线程的测试demo时,一般都是用new Thread的方式来创建线程。但是,我们知道创建线程对象,就会在内存中开辟空间,而线程中的任务执行完毕之后,就会销毁。 单个线程的话还好,如果线程的并发数量上来之后,就会频繁的创建和销毁对象。这样,势必会消耗大量的系统资源,进而影响执行效率。 所以,线程池就应运而生。 线程池ThreadPoolExecutor 可以通过idea先看下线程池的类图,了解一下它的继承关系和大概结构。 它继承自AbstractExecutorService类,这是一个抽象类,不过里边的方法都是已经实现好的。然后这个类实现了ExecutorService接口,里边声明了各种方法,包括关闭线程池,以及线程池是否已经终止等。此接口继承自父接口Executor,里边只声明了一个execute方法。 线程池就是为了解决单个线程频繁的创建和销毁带来的性能开销。同时,可以帮我们自动管理线程。并且不需要每次执行新任务都去创建新的线程,而是重复利用已有的线程,大大提高任务执行效率。 我们打开 ThreadPoolExecutor的源码,可以看到总共有四个构造函数。 但是,前三个最终都会调用到最后一个构造函数。我们来看下这个构造函数都有哪些参数。(其实,多看下参数的英文解释就能明白其中的含义,看来英语对程序员来说是真的重要呀) //核心构造函数 public

9 -【 线程池 】- 7 ExecutorService 执行器服务

半城伤御伤魂 提交于 2020-02-27 02:47:34
1 ExecutorService 执行器服务 java.util.concurrent.ExecutorService 接口表示一个异步执行机制,使我们能够在后台执行任务。因此一个 ExecutorService 很类似于一个线程池。实际上,存在于 java.util.concurrent 包里的 ExecutorService 实现就是一个线程池实现。 1.1 ExecutorService 例子 以下是一个简单的 ExecutorService 例子: //线程工厂类创建出线程池 ExecutorService executorService = Executors . newFixedThreadPool ( 10 ) ; //执行一个线程任务 executorService . execute ( new Runnable ( ) { public void run ( ) { System . out . println ( "Asynchronous task" ) ; } } ) ; //线程池关闭 executorService . shutdown ( ) ; 上面代码首先使用 newFixedThreadPool() 工厂方法创建一个 ExecutorService。这里创建了一个十个线程执行任务的线程池。然后,将一个 Runnable 接口的匿名实现类传递给

9 -【 线程池 】- 8 ScheduledPoolExecutor 定时线程池执行者

让人想犯罪 __ 提交于 2020-02-26 22:10:12
1 ScheduledPoolExecutor 定时线程池执行者 java.util.concurrent.ScheduledExecutorService 是一个 ExecutorService, 它能够将任务延后执行,或者间隔固定时间多次执行。 任务由一个工作者线程异步执行,而不是由提交任务给 ScheduledExecutorService 的那个线程执行。 1.1 ScheduledPoolExecutor 例子 ScheduledExecutorService scheduledExecutorService = Executors . newScheduledThreadPool ( 5 ) ; ScheduledFuture scheduledFuture = scheduledExecutorService . schedule ( new Callable ( ) { public Object call ( ) throws Exception { System . out . println ( "Executed!" ) ; return "Called!" ; } } , 5 , TimeUnit . SECONDS ) ; //5秒后执行 首先一个内置 5 个线程的 ScheduledExecutorService 被创建。之后一个 Callable

Netty快速入门(10)Reactor与Netty

∥☆過路亽.° 提交于 2020-02-26 18:09:31
Reactor模式 Reactor是1995年由道格拉斯提出的一种高性能网络编程模式。由于好多年了,当时的一些概念与现在略有不同,reactor模式在网络编程中是非常重要的,可以说是NIO框架的典型模式,一些经典的框架,比如Mina、Netty、Cindy都是此模式的实现。 我们来看看当年提出的通用模型: 上面的图形中: > 1、Handle 可以理解为资源或者文件句柄,放在netty里面就是channel,就是我们实际要处理的东西 > > 2、Event Handler和Concrete Event Handler 就是具体的事件处理器,对应netty中的handler接口和具体的handler > > 3、Synchronous Event Demultiplexer同步事件多路复用分发器,可以理解为nio中的select > > 4、Initiation Dispatcher,分发器,可以理解为nio中的循环,也就是netty中的EventLoop,处理各种事件 > > 5、select(handlers)就是真正处理业务的地方 大家注意上面图形中的几个箭头,可以看出各个组件之间的关联关系。这个经典的模型当时并不是针对Java提出的,任何拥有这些组件的语言,都可以实现高性能的reactor模型。 单线程Reactor 基于Java,Doug Lea(Java并发包作者

线程池源码解析

早过忘川 提交于 2020-02-26 11:55:17
前言   Java提供了若干种线程池,常用的线程池是ThreadPoolExecutor,其中用于提交任务的方法是execute以及submit方法,其中submit最终也是会调用execute方法,所以这里只介绍excute及其相关方法。   在介绍源码之前,希望读者对于线程池参数有基本了解会有助于理解代码,可以查看这篇文章 https://juejin.im/post/5cae9b42f265da03705fa152 。 主要成员变量 1 // 线程池状态量,高3未用于表示线程池运行状态,低29位用于表示线程池的线程数 2 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); 3 private static final int COUNT_BITS = Integer.SIZE - 3; 4 // 线程池最大容量,这里是程序硬性规定的最大数量,优先级高于maximumPoolSize 5 private static final int CAPACITY = (1 << COUNT_BITS) - 1; 6 7 // 线程池运行状态 8 private static final int RUNNING = -1 << COUNT_BITS; 9 private static final

Java学习-线程池

孤街醉人 提交于 2020-02-26 01:53:36
线程池的概念和原理 线程池的代码实现 /* 2.创建一个类,实现Runnable接口,重写run方法,设置线程任务 */ public class RunnableImpl implements Runnable { @Override public void run ( ) { System . out . println ( Thread . currentThread ( ) . getName ( ) + "创建了一个新的线程执行" ) ; } } import java . util . concurrent . ExecutorService ; import java . util . concurrent . Executors ; /* 线程池:JDK1.5之后提供的 java.util.concurrent.Executors:线程池的工厂类,用来生成线程池 Executors类中的静态方法: static ExecutorService newFixedThreadPool(int nThreads) 创建一个可重用固定线程数的线程池 参数: int nThreads:创建线程池中包含的线程数量 返回值: ExecutorService接口,返回的是ExecutorService接口的实现类对象,我们可以使用ExecutorService接口接收(面向接口编程

【转载】Java编程的逻辑 (78) - 线程池

丶灬走出姿态 提交于 2020-02-26 01:52:26
上节,我们初步探讨了Java并发包中的任务执行服务,实际中,任务执行服务的主要实现机制是线程池,本节,我们就来探讨线程池。 基本概念 线程池,顾名思义,就是一个线程的池子,里面有若干线程,它们的目的就是执行提交给线程池的任务,执行完一个任务后不会退出,而是继续等待或执行新任务。线程池主要由两个概念组成,一个是任务队列,另一个是工作者线程,工作者线程主体就是一个循环,循环从队列中接受任务并执行,任务队列保存待执行的任务。 线程池的概念类似于生活中的一些排队场景,比如在火车站排队购票、在医院排队挂号、在银行排队办理业务等,一般都由若干个窗口提供服务,这些服务窗口类似于工作者线程,而队列的概念是类似的,只是,在现实场景中,每个窗口经常有一个单独的队列,这种排队难以公平,随着信息化的发展,越来越多的排队场合使用虚拟的统一队列,一般都是先拿一个排队号,然后按号依次服务。 线程池的优点是显而易见的: 它可以重用线程,避免线程创建的开销 在任务过多时,通过排队避免创建过多线程,减少系统资源消耗和竞争,确保任务有序完成 Java并发包中线程池的实现类是ThreadPoolExecutor,它继承自AbstractExecutorService,实现了ExecutorService,基本用法与上节介绍的类似,我们就不赘述了。不过,ThreadPoolExecutor有一些重要的参数

Tomcat 核心配置

倖福魔咒の 提交于 2020-02-25 19:15:55
tomcat的核心配置在conf/server.xml中。 <Server> 根元素 <Server>即Catalina Servlet组件。 <Server port="8005" shutdown="SHUTDOWN"> 常用属性 Address—Tomcat监听shutdown命令的地址,默认为localhost className—指定实现org.apache.catalina.Server接口的类,默认值为org.apache.catalina.core.StandardServer port-Tomcat监听shutdown命令的端口。设置为-1,则禁止通过端口关闭Tomcat,同时shutdown.bat也不能使用 shutdown-通过指定的地址(Address)、端口(port)关闭Tomcat所需的字符串。 shutdown属性使用示例 启用Telnet:(Telnet是windows自带的与其它主机通信的程序) win+s,输入telnet,匹配“启用或关闭windows功能”,回车,勾选telent 命令行输入 telnet 启动Telnet 输入 telnet localhost 8005 连接到指定主机(此处为本地主机) 输入 SHUTDOWN 即可关闭Tomcat 输入 quit 可退出Telnet <Server>有3个子元素:<Listener>、

3.Hystrix断路器

回眸只為那壹抹淺笑 提交于 2020-02-25 02:02:13
1.为什么需要断路器 1.1存在问题 在理想状态下,一个应用依赖的服务都是健康可用的,我们可以正常处理所有的请求。默认情况下tomcat只有一个线程池去处理的客户端发送的所有服务请求,这样在高并发情况下,如果客户端所有的请求堆积到同一个服务接口上,就会产生tomcat的所有线程池去处理该服务接口,可能会导致其他服务奔溃。 1.2简介 Hystrix,英文意思是豪猪,全身是刺,看起来就不好惹,是一种保护机制。 Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。 1.3雪崩效应 在复杂的微服务架构中的应用程序有很多的依赖,都会不可避免地在某些时候失败。高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险。一个请求,可能需要调用多个微服务接口才能实现,会形成非常复杂的调用链路: 如图,一次业务请求,需要调用A、H、I、P四个服务,这四个服务又可能调用其它服务。 如果此时某个服务出现异常: 例如微服务I发生异常,请求阻塞,用户不会得到响应,则tomcat的这个线程不会释放,于是越来越多的用户请求到来,越来越多的线程会阻塞: 服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务不可用,形成雪崩效应。 Hystrix解决雪崩问题的手段包括: 线程隔离 服务熔断 服务降级 1.4 解决方法和原理

java常用的几种线程池比较

こ雲淡風輕ζ 提交于 2020-02-25 02:00:12
1. 为什么使用线程池 诸如 Web 服务器、数据库服务器、文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务。请求以某种方式到达服务器,这种方式可能是通过网络协议(例如 HTTP、FTP 或 POP)、通过 JMS 队列或者可能通过轮询数据库。不管请求如何到达,服务器应用程序中经常出现的情况是:单个任务处理的时间很短而请求的数目却是巨大的。 构建服务器应用程序的一个简单模型是:每当一个请求到达就创建一个新线程,然后在新线程中为请求服务。实际上对于原型开发这种方法工作得很好,但如果试图部署以这种方式运行的服务器应用程序,那么这种方法的严重不足就很明显。每个请求对应一个线程(thread-per-request)方法的不足之一是:为每个请求创建一个新线程的开销很大;为每个请求创建新线程的服务器在创建和销毁线程上花费的时间和消耗的系统资源要比花在处理实际的用户请求的时间和资源更多。 除了创建和销毁线程的开销之外,活动的线程也消耗系统资源。在一个 JVM 里创建太多的线程可能会导致系统由于过度消耗内存而用完内存或“切换过度”。为了防止资源不足,服务器应用程序需要一些办法来限制任何给定时刻处理的请求数目。 线程池为线程生命周期开销问题和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。其好处是