线程池

线程池的底层实现你了解吗?线程池模块总结【上篇】

六眼飞鱼酱① 提交于 2020-03-09 23:39:44
大家好,这是一个为了梦想而保持学习的博客。这是第四篇文章,分享一下我对【线程池】的理解。 文章的风格会一直保持问答的方式讲述,这是我个人喜欢的一种风格,也是相当于模拟面试。 线程池的核心理念是什么? 由我的第一篇关于 线程 的文章中提到的,我们服务器的线程资源是宝贵且有限的,因此我们在某些场景下需要尽可能的复用线程,不让线程频繁的创建与销毁。因此就引出了我们线程池的第一个核心理念: 线程资源复用 。 那么除开线程资源复用之外,我们还希望能对线程资源的使用情况进行一些控制,例如最少要有几个线程在跑,最多能创建多少个线程。那么就引出了我们线程池第二个核心理念: 线程资源控制 。 线程池的核心功能是如何实现的呢? 线程资源复用的实现原理 为了彻底了解线程池的工作原理,肯定是要从源码开始说起的。本文选取的核心类是ThreadPoolExecutor,这个也是《Java并发编程之美》书中用来讲解的类。首先我们从核心函数 void execute(Runnable command) 开始看起。 下面的源码看起来实在枯燥,我还是在最前面先概述一下原理,让读者能有个大概印象,然后画图阐述下具体执行流程。至于下面的代码块,可以在各位读者阅读源码的时候,再来结合这里的说明进行理解。 线程池对核心线程的复用,主要是通过内部Worker线程+生产者消费者模式去实现的

线程池-实现一个取消选项

不想你离开。 提交于 2020-03-09 09:46:24
三种方式 通过使用轮循操作来检查IsCancellationRequested是否为true,是则需要取消当前操作过程(直接使用return) 通过抛出一个OperationCanceledException异常来终止操作(操作之外的代码控制取消过程) 注册一个回调函数(操作取消时,线程池将调用该函数) static void Main(string[] args) { using (var cts = new CancellationTokenSource()) { CancellationToken token = cts.Token; ThreadPool.QueueUserWorkItem(_ => AsyncOperation1(token)); Thread.Sleep(TimeSpan.FromSeconds(2)); cts.Cancel();//传达取消请求 } using (var cts = new CancellationTokenSource()) { CancellationToken token = cts.Token; ThreadPool.QueueUserWorkItem(_ => AsyncOperation2(token)); Thread.Sleep(TimeSpan.FromSeconds(2)); cts.Cancel();/

Netty(1)线程模型

|▌冷眼眸甩不掉的悲伤 提交于 2020-03-09 05:00:35
前言 对于Netty框架的学习 前置知识点:线程模型 目录 线程模型概述 传统阻塞IO线程模型 Reactor基本思想 单Reactor单线程 单Reactor多线程 主从Reactor多线程 总结 线程模型概述 在学习Netty线程模型之前,先要搞清楚各个线程模型的发展过程,再进行Netty线程模型的了解 现有的线程模型: 传统阻塞IO线程模型(也就是BIO) Reactor 模式 其中Reactor模式根据Reactor的数量和线程的数量可以分为三种: 单Reactor单线程 单Reactor多线程 主从Reactor多线程 Netty框架是基于主从Reactor多线程模型进行改进(多个主Reactor) 传统阻塞IO线程模型 传统阻塞IO也就是Java BIO 很简单,就是一个连接一个线程的模型 每一个连接都创建一个线程去处理,而且当完成连接,读取数据时,如果没有数据可读会阻塞线程 传统阻塞IO线程模型缺点: 对于高并发的环境,会创建很多线程,系统开销大 阻塞IO模式会造成线程浪费 Reactor基本思想 Reactor模式是对传统阻塞IO模型的一种改进 其中基本思想有两个: 基于 I/O 复用模型 :多个连接共用一个阻塞对象,应用程序只需要在一个阻塞对象等待,无需阻塞等待所有连接。当某个连接有新的数据可以处理时,操作系统通知应用程序,线程从阻塞状态返回,开始进行业务处理

JUC知识点汇总

左心房为你撑大大i 提交于 2020-03-08 20:55:57
JUC汇总 总结: 总结: 通常说的并发包即java.util.concurrent及其子包,集中了Java并发的各种基础工具类,具体: 提供了比Synchronized更高级的各种同步结构:CountDownLatch、CyclicBarrier、Semaphore等,可实现更丰富的多线程操作,例如用Semaphore作为资源控制器,限制同时工作的线程数量。 JUC之各种同步结构(Semaphore、CountDownLatch、CyclicBarrier) 各种线程安全容器:ConcurrentHashMap、有序的ConcurrentSkipListMap或通过快照机制,实现线程安全的动态数组CopyOnWriteArrayList JUC之各种线程安全容器 各种并发队列,各种BlockedQueue实现,如ArrayBlockingQueue、SynchronousQueue,或针对塔顶场景的PriorityBlockingQueue等 JUC 之各种并发队列Concurrent、CopyOnWrite、Blocking 强大的Executor框架,可创建不同类型的线程池,绝大部分情况下不需要自己从头实现线程池和任务调度器 JUC之各种线程池 补充知识点: Unsafe机制补充 并发包内部组成AQS 和 CAS 来源: CSDN 作者: 来柯 链接: https:/

Python3爬虫(十二) 爬虫性能

陌路散爱 提交于 2020-03-08 17:24:56
Infi-chu: http://www.cnblogs.com/Infi-chu/ 一、简单的循环串行 一个一个循环,耗时是最长的,是所有的时间综合 import requests url_list = [ 'http://www.baidu.com', 'http://www.pythonsite.com', 'http://www.cnblogs.com/' ] for url in url_list: result = requests.get(url) print(result.text) 二、通过线程池 整体耗时是所有连接里耗时最久的那个,相对于循环来说快了不少 import requests from concurrent.futures import ThreadPoolExecutor def fetch_request(url): result = requests.get(url) print(result.text) url_list = [ 'http://www.baidu.com', 'http://www.bing.com', 'http://www.cnblogs.com/' ] pool = ThreadPoolExecutor(10) for url in url_list: #去线程池中获取一个线程,线程去执行fetch_request方法

如何实现处理线程的返回值?

ⅰ亾dé卋堺 提交于 2020-03-08 16:46:01
1、主线程等待法 缺点:需要自己实现循环等待的逻辑,当需要等待的变量较多时,代码异常臃肿。 2、使用thread类的join()阻挡当前线程以等待子线程处理完毕。 缺点:控制力度不够精细。 3、通过callable接口实现,通过FutureTask Or 线程池获取。 一、那么,直接上代码吧,我们首先开始第一种方法。先创建一个类CycleWait,如下所示: public class CycleWait implements Runnable { private String value ; @Override public void run ( ) { try { Thread . currentThread ( ) . sleep ( 5000 ) ; } catch ( InterruptedException e ) { e . printStackTrace ( ) ; } value = "we have date now" ; } public static void main ( String [ ] args ) throws InterruptedException { CycleWait wait = new CycleWait ( ) ; Thread thread = new Thread ( wait ) ; thread . start ( ) ; /

线程池源码-伟大而渺小的ctl

落爺英雄遲暮 提交于 2020-03-08 10:58:14
最近看到有些博客提到线程池需要掌握的问题清单,发现自己很多地方是是一知半解的状态,正好借此机会,带着问题去回顾了一波 Java 线程池的源码。 ctl 为何物? 线程池的运作过程对状态的检查非常严格,几乎是走两步一个检查,检查线程池的状态,有效线程的数目,而它们都是基于一个整型变量来实现的,它的「身子」也许很单薄,但是肩上的责任重大。 // 本质是 Integer 型变量,进行了原子性的封装 private final AtomicInteger ctl = new AtomicInteger ( ctlOf ( RUNNING , 0 ) ) ; 一饰两角 大家可能会想,一个变量怎么能够同时表示两个状态,我当时也非常疑惑,这里就要提到一个巧妙的设计——高低位表示法(名字是我瞎掰的)。 1.紧随在 ctl 变量后面被初始化的两个变量 private static final int COUNT_BITS = Integer . SIZE - 3 ; private static final int CAPACITY = ( 1 << COUNT_BITS ) - 1 ; COUNT_BITS 的值为 29(整型 32 位); CAPACITY = 1 << 29 表示将 1 往左移动了 29 位,换算之后就是 1 * 2 的 29 次方,高 3 位被空出来了,而低 29 位用来表示

[内功修神]Java NIO

微笑、不失礼 提交于 2020-03-07 23:46:48
个人博客文章地址 文章目录 1. 浅析I/O模型 1.1. 什么是同步?什么是异步? 1.2. 什么是阻塞?什么是非阻塞? 1.3. 什么是阻塞IO?什么是非阻塞IO? 1.4. 什么是同步IO?什么是异步IO? 1.5. 五种IO模型 1.5.1. 阻塞IO模型(BIO) 1.5.2. 非阻塞IO模型 1.5.3. 多路复用IO模型(NIO) 1.5.4. 信号驱动IO模型 1.5.5. 异步IO模型 (Asynchronous IO --- AIO) 1.6. 两种高性能IO设计模式 1.6.1. 传统的网络服务设计模式中,有两种比较经典的模式 1.6.2. Reactor模式 1.6.3. Proactor模式 2. Java NIO之Buffer(缓冲区) 3. Java NIO之通道(Channel) 4. 选择器(Selector) 1. 浅析I/O模型 1.1. 什么是同步?什么是异步? 同步:如果有多个任务或者事件要发生,这些任务或者事件必须逐个地进行,一个事件或者任务的执行 会导致整个流程的暂时等待 ,这些事件没有办法并发地执行; 异步:如果有多个任务或者事件发生,这些事件可以并发地执行,一个事件或者任务的执行 不会导致整个流程的暂时等待 。 1.2. 什么是阻塞?什么是非阻塞? 阻塞:当某个事件或者任务在执行过程中,它发出一个请求操作

JUC并发编程(五):快速了解线程池

时光毁灭记忆、已成空白 提交于 2020-03-07 18:43:33
池化技术 首先我们要了解的一个东西就是程序运行的本质是占用系统资源! 所以我们为了提高程序的使用效率,降低我们的一个性能消耗,就要把一些频繁创建的资源提前给准备好,这就是池化技术. 常见的有线程池,连接池,内存池,对象池… 其次我们为什么要用线程池-- 多路复用 关于线程池,我们只要掌握三大方法,七大参数,四种拒绝策略即可!下 三大方法 newFixedThreadPool(),newCachedThreadPool(),newSingleThreadExecutor() public class Test1 { public static void main ( String [ ] args ) { //线程池 Executors原生三大方法 //固定大小 ExecutorService threadpool1 = Executors . newFixedThreadPool ( 5 ) ; //弹性收缩 ExecutorService threadpool2 = Executors . newCachedThreadPool ( ) ; //只有一个 ExecutorService threadpool3 = Executors . newSingleThreadExecutor ( ) ; try { for ( int i = 1 ; i <= 10 ; i ++ ) {

如果优雅地关闭ExecutorService提供的java线程池

自古美人都是妖i 提交于 2020-03-07 18:09:21
ExecutorService让我们可以优雅地在程序中使用线程池来创建和管理线程,而且性能佳、开销小,还可以有效地控制最大并发线程数,是我们在java并发编程中会经常使用到的。 每一个线程都会占用系统资源,因此线程池的关闭与清理同样重要,本文介绍我们如何优雅地关闭线程池。 一. ExecutorService中关闭线程池的方法 1. shutdown() 停止接收新任务,原来的任务继续执行 停止接收新的submit的任务; 已经提交的任务(包括正在跑的和队列中等待的),会继续执行完成; 等到第2步完成后,才真正停止; 2. shutdownNow() 停止接收新任务,原来的任务停止执行 跟 shutdown() 一样,先停止接收新submit的任务; 忽略队列里等待的任务; 尝试将正在执行的任务interrupt中断; 返回未执行的任务列表; 说明:它试图终止线程的方法是通过调用 Thread.interrupt() 方法来实现的,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt() 方法是无法中断当前的线程的。所以,shutdownNow() 并不代表线程池就一定立即就能退出,它也可能必须要等待所有正在执行的任务都执行完成了才能退出。但是大多数时候是能立即退出的。 3. awaitTermination(long