线程池

学习Java第三十天--多线程之线程池和同步锁

半城伤御伤魂 提交于 2020-03-16 18:21:05
线程池、Callable接口、Future接口、Lock接口、同步锁的使用方法 14.4 线程池 14.4.1 线程池概念 14.4.2 线程池原理 14.4.3 获取线程池 14.4.4 Callable接口 14.4.5 Future接口 14.4.6 线程的同步 14.4.7 线程的异步 14.4.8 Lock接口 14.4.8 重入锁 14.4.9 读写锁 14.4.10 ReentrantReadWriteLock 14.4 线程池 14.4.1 线程池概念 现有问题: 线程是宝贵的内存资源、单个线程约占1MB空间,过多分配易造成内存溢出; 频繁的创建及销毁线程会增加虚拟机回收频率、资源开销,造成程序性能下降; 线程池: 线程容器,可设定线程分配的数量上限; 将预先创建的线程对象存入池中,并重用线程池中的线程对象 避免频繁的创建和销毁; 14.4.2 线程池原理 将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程; 14.4.3 获取线程池 常用的线程池接口和类(所在包java.util.concurrent) Executor:线程池的顶级接口 ExecutorService:线程池接口,可通过submit(Runnable task)提交任务代码; Executors工厂类:通过此类可以获得一个线程池; 通过newFixedThreadPool

线程池(ThreadPool)使用和原理

房东的猫 提交于 2020-03-16 12:40:52
通常我们构建线程池一般使用这种方式 ExecutorService executorService = Executors.newFixedThreadPool(4); //固定线程池 但是阿里开发手册上面建议使用以下方式 ThreadPoolExecutor(int corePoolSize, //核心线程池 int maximumPoolSize, //最大线程池 long keepAliveTime, //超时时间 TimeUnit unit, //时间单位 BlockingQueue<Runnable> workQueue, //队列 ThreadFactory threadFactory, //线程工厂 RejectedExecutionHandler handler) //拒绝策略 其实两种构建线程池的方式并没有什么本质的区别,阿里推荐的方式只是为了让线程池构建清楚的知道线程池的参数,避免过度内存开销和浪费 线程池五种状态 下面我们就分析下线程池工作的流程 executorService.execute(new Thread()); executorService.shutdown(); public void execute(Runnable command) { if (command == null) throw new NullPointerException(

线程池(一)

泪湿孤枕 提交于 2020-03-16 12:39:37
Executor 线程池顶级接口。定义方法,void execute (Runnable)。方法调用者提供Runnable接口的实现,线程池通过线程执行这个Runnable。服务方法无返回值的,是Runnable接口中的run方法无返回值。 作用是: 启动线程任务的。 ExecutorService Executor接口的子接口。提供了一个新的服务方法,submit。有返回值(Future类型)。submit方法提供了overload方法。其中有参数类型为Runnable的,不需要提供返回值的;有参数类型为Callable,可以提供线程执行后的返回值。 - void execute(Runnable), Future submit(Callable), Future submit(Runnable) Future 未来结果,代表线程任务执行结束后的结果。 获取线程执行结果的方式是通过get方法获取的。get无参,阻塞等待线程执行结束,并得到结果。get有参,阻塞固定时长,等待线程执行结束后的结果,如果在阻塞时长范围内,线程未执行结束,抛出异常。 常用方法: T get() T get(long, TimeUnit) Callable 可执行接口。 类似Runnable接口。也是可以启动一个线程的接口。其中定义的方法是call

线程池原理分析

不想你离开。 提交于 2020-03-16 12:39:04
线程池原理分析 应用线程池代码 public class ThreadPoolDemo implements Runnable{ static ExecutorService executorService = Executors.newFixedThreadPool(3); @Override public void run() { try { TimeUnit.SECONDS.sleep(10); } catch (Exception e) { e.printStackTrace(); } System.out.println("name:" + Thread.currentThread().getName()); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { ThreadPoolDemo threadPoolDemo = new ThreadPoolDemo(); executorService.execute(threadPoolDemo); } executorService.shutdown(); } } 线程池创建大致分为5种: static ExecutorService executorService = Executors.newFixedThreadPool

线程池与非线程池应用场景及模型对比分析

喜欢而已 提交于 2020-03-16 11:59:44
某厂面试归来,发现自己落伍了!>>> 在网络编程中经常用到线程池和连接池,今天就对其中常用的线程池的基本应用场景和模型做个简单的对比分析。 1、 业务流程对比 a、 非线程池业务流模型: 上图标识了基本的非线程池的线程模型,前端 1 有多少连接则前端客户端 2 与前端服务器端 3 均需建立一对一的线程数进行响应的连接。前端服务器端 3 与后端服务器端 4 也需建立响应数目的线程进行连接处理相关业务。 当一个任务处理完毕后线程退出,在下一个任务到来的时候前端服务器端创建新的线程来处理新的任务。 b 、线程池模型: 上图标识了基本的线程池模型。前端客户端大量的连接通过服务端的任务接收线程将连接任务放入前端服务器端的任务队列中,前端服务器端起固定数量的处理线程处理前端的任务,当处理线程处理完任务后从任务队列中获取下一个处理任务。保证了前端服务器端和后端服务器端的连接数不会超过前端服务器端的处理任务线程数 n ,从而保证了后端服务器端的压力。 当处理线程处理完一个任务而任务队列中没有任务的时候线程并不退出,阻塞等待新的任务。 通过上图可以看出,当前端服务器端通过设置合理的处理线程数和任务队列大小,可以有效的屏蔽前端客户端高并发量对后端服务器端的冲击。 2、 应用场景分析对比 a、 非线程池模型 适用于单次连接任务执行时间较长,并发量不高的情况。一旦并发量很高则线程频繁创建的开销是巨大的。

手动实现线程池 ThreadPool

你说的曾经没有我的故事 提交于 2020-03-16 11:56:41
Executors提供了三个经典的线程池创建方式 ExecutorService threadPool = Executors.newFixedThreadPool(int) ExecutorService threadPool = Executors.newSingleThreadPool() ExecutorService threadPool = Executors.newCachedThreadPool(int) 那我们在工作中到底用哪一个呢? 答案是我们在生产上只能用自定义的 根据图中我们可以发现他们得底层实现都是用了ThreadPoolExecutor,然而第五个参数使用到的阻塞队列默认值是Integer.MAX_VALUE,也就是 2147483647,这样就相当于是一个无界的队列。所有的请求都往里塞,最终造成OOM。 根据阿里编码规范也可以看出 参数说明 线程池底层实现的7大参数 1.corePoolSize:线程池中的常驻核心线程数 2.maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1 3.keepAliveTime:多余的空闲线程的存活时间 4.unit:keepAliveTime的单位 5.workQueue:任务队列,被提交但尚未被执行的任务。 6.threadFactory:表示生成线程池中工作线程的线程工厂

并发编程之线程池合理配置

戏子无情 提交于 2020-03-16 11:49:26
某厂面试归来,发现自己落伍了!>>> 如何合理的配置线程池参数: 思考该问题首先明确两个任务类型的概念 CPU密集:该任务需要进行大量的计算,但是并没有阻塞,CPU在全速的运行。值得注意的是CPU密集型的任务只有在真正的多核CPU上才能更好的发挥作用(多线程技术),单核的CPU模拟多线程并不能提高任务的执行速度,因为CPU 的计算能力是有限的。 IO密集:指的是该任务的IO操作,也就是说会存在阻塞的情况。这种任务会导致CPU浪费很多时间在等待上,因此这种类型的任务使用多线程技术能更好的提高计算集的任务执速度,即使是单核的计算机采用模拟多线程技术也能减少CPU等待IO的阻塞时间。 具体配置参考如下: CPU密集型任务=CPU核数+1 IO密集型任务 = 2*CPU核数 来源: oschina 链接: https://my.oschina.net/u/3670669/blog/3195873

线程池ThreadPool

妖精的绣舞 提交于 2020-03-16 08:28:25
线程池要在执行execute时才会正式创建线程 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)线程池7大参数 corePoolSize:线程池中心的常驻核心线程数 maximumPoolSize:线程池中能够容纳同时执行的最大线程数,此值必须要大于等于! keepAliveTime:多余的空间线程的存活时间,当前池中线程数量超过corePoolSize时,当空闲时间达到keepAliveTime,多余线程会被销毁直到只剩下corePoolSize个线程为止 TimeUnit:KeepAliveTime的单位 workQueue:任务队列,被提交但尚未被执行的任务 threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程,一般默认即可 handler:拒绝策略,表示当前队列满了,并且工作线程大于等于线程池的最大线程数时如何拒绝请求执行的runnable的策略 public static ExecutorService

Netty源码—一、server启动(1)

淺唱寂寞╮ 提交于 2020-03-16 05:26:12
说明:netty源码系列是基于4.1.25版本的netty源码的 Netty作为一个Java生态中的网络组件有着举足轻重的位置,各种开源中间件都使用Netty进行网络通信,比如Dubbo、RocketMQ。可以说Netty是对Java NIO的封装,比如ByteBuf、channel等的封装让网络编程更简单。 在介绍Netty服务器启动之前需要简单了解两件事: reactor线程模型 linux中的IO多路复用 reactor线程模型 关于reactor线程模型请参考 这篇文章 ,通过不同的配置Netty可以实现对应的三种reactor线程模型 reactor单线程模型 reactor多线程模型 reactor主从多线程模型 // reactor单线程模型,accept、connect、read、write都在一个线程中执行 EventLoopGroup group = new NioEventLoopGroup(1); bootStrap.group(group); // reactor多线程,accept在bossGroup中的一个线程执行,IO操作在workerGroup中的线程执行 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new

并发编程之线程池原理分析

别说谁变了你拦得住时间么 提交于 2020-03-15 23:19:38
线程池原理: 提交一个任务到线程池中,线程池的处理流程如下: 判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。 断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。 判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。 来源: oschina 链接: https://my.oschina.net/u/3670669/blog/3195487