JAVA并发编程(一)JAVA线程池的使用

【Latex】【附安装文件】Miktex和TexStudio的安装与配置 这代表“构建并运行”,一般来说,我们只需要点这个按钮来运行Latex代码。保存一下代码文件,再运行一次,PDF文件会出现在与代码文件相同的文件夹下。安装完成后,你可能会跳转到一个页面中,你看到这个页面就意味着安装成功了。其实不需要你敲,你只要将下面的代码复制粘贴到你刚刚的文件中即可。成功安装MikTex后,我们需要进行更新,减少后续使用的麻烦。如果懂得将安装路径设置在你想要的盘中,你可以自己设置。双击上文的.exe文件后,你会看到如下画面。如果不懂,为避免不必要的麻烦,请直接点击“ 阅读详情

概述

new Thread的弊端如下:
a. 每次new Thread新建对象性能差。
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。

如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?在Java中可以通过线程池来达到这样的效果。

Java 线程池

Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

无论使用哪种方式创建,最终返回的都是ThreadPoolExecutor,而方法返回是ExecutorService,ThreadPoolExecutor继承了AbstractExecutorService,而AbstractExecutorService实现了ExecutorService这个接口,
ExecutorService这个接口继承了Executor。ThreadPoolExecutor is-aExecutorService。

ThreadPoolExecutor构造方法

线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:
ThreadPoolExecutor(

int corePoolSize,//线程池维护线程的最少数量

int maximumPoolSize,//线程池维护线程的最大数量

long keepAliveTime,//线程池维护线程所允许的空闲时间

TimeUnit unit, //线程池维护线程所允许的空闲时间的单位

BlockingQueue<Runnable> workQueue, //线程池所使用的缓冲队列,

                                                                 //主要使用ArrayBlockingQueue, LinkedBlockingQueue, SynchronousQueue

ThreadFactory threadFactory,//线程工厂

RejectedExecutionHandler handler// 线程池对拒绝任务的处理策略

)

参数的详细含义:
corePoolSize:核心池的大小。在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,是预创建线程的意思,即在没有任务到来之前就创corePoolSize个线程或者一个线程。默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。
maximumPoolSize:线程池最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建多少个线程。
keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;
unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:
TimeUnit.DAYS;               //天
TimeUnit.HOURS;             //小时
TimeUnit.MINUTES;           //分钟
TimeUnit.SECONDS;           //秒
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.NANOSECONDS;       //纳秒
workQueue:一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响,一般来说,这里的阻塞队列有以下几种选择:
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;
ArrayBlockingQueue和PriorityBlockingQueue使用较少,一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
threadFactory:线程工厂,主要用来创建线程;
handler:表示当拒绝处理任务时的策略,有以下四种取值:
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

提交任务

我们可以使用execute提交的任务,但是execute方法没有返回值,所以无法判断任务是否被线程池执行成功。

threadsPool.execute(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
            }
        });
我们也可以使用submit 方法来提交任务,它会返回一个future,那么我们可以通过这个future来判断任务是否执行成功,通过future的get方法来获取返回值,get方法会阻塞住直到任务完成,而使用get(long timeout, TimeUnit unit)方法则会阻塞一段时间后立即返回,这时有可能任务没有执行完。

Future<Object> future = executor.submit(harReturnValuetask);
try {
     Object s = future.get();
} catch (InterruptedException e) {
    // 处理中断异常
} catch (ExecutionException e) {
    // 处理无法执行任务异常
} finally {
    // 关闭线程池
    executor.shutdown();
}

终止线程池

ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:
shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务

如何选择合理的线程池

计算密集型,就是应用需要非常多的CPU计算资源,在多核CPU时代,我们要让每一个CPU核心都参与计算,将CPU的性能充分利用起来,这样才算是没有浪费服配置,如果在非常好的配置上还运行着单线程程序那将是多么重大的浪费。对于计算密集型的应用,完全是靠CPU的核数来工作,所以为了让它的优势完全发挥出来,避免过多的线程上下文切换,比较理想方案是:计算密集型的较理想线程数 = CPU内核线程数+1。
对于IO密集型的应用,读写数据库,读写文件都涉及到IO,一旦发生IO,线程就会处于等待状态,当IO结束,数据准备好后,线程才会继续执行。因此从这里可以发现,对于IO密集型的应用,我们可以多设置一些线程池中线程的数量,这样就能让在等待IO的这段时间内,线程可以去做其它事,提高并发处理效率。比较合适的方案是:IO密集型应用比较理想线程数= CPU内核线程数*2+1。
Android中,AsyncTask的中源码:


private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);


创建的线程池个数介于计算密集型和IO密集型之间,算是比较通用的。

RXjava中,对线程池创建提供了很好的控制:

调度器类型效果
Schedulers.computation( )用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io());默认线程数等于处理器的数量
Schedulers.from(executor)使用指定的Executor作为调度器
Schedulers.immediate( )在当前线程立即开始执行任务
Schedulers.io( )用于IO密集型任务,如异步阻塞IO操作,这个调度器的线程池会根据需要增长;对于普通的计算任务,请使用Schedulers.computation();Schedulers.io( )默认是一个CachedThreadScheduler,很像一个有线程缓存的新线程调度器
Schedulers.newThread( )为每个任务创建一个新线程
Schedulers.trampoline( )当其它排队的任务完成后,在当前线程排队开始执行



欢迎扫描二维码,关注公众号






HFSS仿真3dB微带双分支定向耦合器学习笔记 设计一个3dB微带双分支定向耦合器,各端口微带线特性阻抗为50Ω,中心频率为5GHz,介质基板的介电常数9.6,基板厚度为0.8mm这里重点讲解HFSS的操作,关于理论知识后面文章更新。 阅读详情

相关推荐

Camera 基础知识

Raw Sensor输出的Data格式为Raw,图像的效果处理使用BB端的ISP,BB端接收Raw data后进行一系列的图像处理(OB,Shading,AWB,Gamma,EE,ANR等),效果方面由BB端控制,需要针对不同的模组进行效果调试,Raw sensor是目前的主流,数据量比YUV Sensor小(RAW10 格式的sensor 1个pixel 10个bit)使用平台ISP处理,能支持较大的size。不过,相位对焦并不是那么完美,它对光线的要求就比较高,在弱光拍摄环境下,相位对焦就无能威力了。

手机-手表蓝牙开发工程师的博客 3062

线程池的5种使用方式

池化思想,不同线程池的创建方式以及差别,线程数设置的经验

a141210104的专栏 6137

AD20/Altium designer——元器件批量命名与编号的高效技巧

本文详细介绍了在AD20/Altium Designer中实现元器件批量命名与编号的高效技巧。通过解析核心的“原理图标注”功能,从基础全局操作到进阶的按模块分区、利用标识符及合并BOM等智能方法,帮助硬件工程师彻底告别手动编号,大幅提升设计效率与文档规范性,并融入了一套完整的实战工作流。

whisky的博客 567

常用线程池介绍

线程池简介 1.线程池概念: 线程池是首先创建一个线程,它们的集合成为线程池。使用线程池可以很好的提升性能,线程池在启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行线程完成后,该线程不会死亡,而是返回线程池中成为空闲状态,等待执行下一个任务。 2.线程池的工作机制 2.1在线程池的编程模式下,任务是提交给整个线程池,而不是直接提交给某个线程,线程池在拿到任务后,就在内部寻找是否有空闲的线程,如果有,则将任务交给某个空闲的线程。 2.2一个线程同时只能执行一个任

NewBie_xW的博客 1055

VulnHub--mrrobot

Vulnhub靶场--Mr robot 靶机

记录笔记 1094

体系结构学习-6-超标量处理器

 MIPS32-5段流水线采用了指令级并行方式(5个流水段同时运行5条指令)提升系统吞吐率,是一种标量处理器(CPI≥1CPI \ge 1CPI≥1),但是一个周期一条指令以及无法满足现代计算机需求了。 超标量处理器(Superscalar) 1、基本思想:增强指令集并行,让每个周期执行更多指令,实现 CPI<1CPI<1CPI<1 。(IPC=1/CPIIPC = 1...

qq_40891899的博客 1210

线程池的使用

java中经常需要用到多线程来处理一些业务,我们非常不建议单纯使用继承Thread或者实现Runnable接口的方式来创建线程,那样势必有创建及销毁线程耗费资源、线程上下文切换问题。同时创建过多的线程也可能引发资源耗尽的风险,这个时候引入线程池比较合理,方便线程任务的管理。java中涉及到线程池的相关类均在jdk1.5开始的java.util.concurrent包中,涉及到的几个核心类及接口包括:Executor、Executors、ExecutorService、ThreadPoolExecutor、F

xiaowang_lj的博客 6099

产品必备技能(十):如何绘制原型图?先要绘制页面流程图+页面原型图!附实操原型图、流程图实例(抖音)

文章目录目标题目实操步骤模板实操【抖音】APP的视频发布功能页面流程绘制页面流程图合格标准绘制页面原型图合格标准 目标 新入行的产品经理都对原型抱有向往的心境,但是有经验的产品经理不会一上来就画原型,而是先画页面流程再来画原型。通过学习,你将学会如何用页面流程图规划用户行为路径、如何借助原型识别问题、减少风险、有效沟通。 题目 任意选择一款你喜欢的产品,体验某个功能,下载并梳理此功能至少5个以上的页面流程跳转点(后面会解释),还原2 - 3个主要界面的低保真原型图。 实操步骤 可使用手绘以及Process

汪雯琦的博客 4836

线程池的使用(7种创建方法)

线程池的7种创建方法

m0_48273471的博客 3万+

机器学习实战26-一种基于LightGBM的股市涨跌预测系统与代码实现过程

在全球经济一体化的背景下,股市作为经济活动的晴雨表,其波动与预测对于投资者、金融机构乃至国家政策制定者而言至关重要。随着金融市场的日益复杂化与信息量的爆炸式增长,股市分析不再仅限于基本面和技术面的传统研究,而是迫切需要更加精准、高效及智能化的方法来捕捉市场动态,以辅助决策制定。模型评估是确保LightGBM股市预测系统准确性和稳定性不可或缺的一环。通过综合运用多种评估指标、科学的验证方法以及深入的性能分析,我们不仅能够全面理解模型的能力和限制,还能为持续优化模型、提升预测准确性奠定坚实基础。

微学AI的博客 2327

【AUTOSAR-RTE】-1-聊一聊RTE(Run-Time Environment)

RTE(Run-Time Environment)是AUTOSAR ECU架构的核心。

「汽车电子助手」的博客 6500

Java并发编程----线程池技术(一)

目录 串行执行任务 一任务一线程 固定线程数量 Executor框架 类库中的线程池 返回任务结果的Callable与Future ---------------------------------笔记来自于《Java并发编程实战》 串行执行任务 以客户端请求服务器为例,同一个时期有多个客户端请求服务器时,单线程中一次只能处理一个客户端的请求,当客户向一个已经被其他客户端...

梦悠哉的博客 398

核磁共振常用的文件格式介绍:NIfTI volume 格式 (*.nii), GIFTI 格式 (*.gii), CIFTI 格式 (*.nii)

NIfTI volume 格式 (*.nii)GIFTI 格式 (*.gii)CIFTI 格式 (*.nii)Scene file文件 (*.scene)规格文件 (*.spec)解剖 (*.annot)一个场景文件包含一个或多个场景;每个场景实际上是保存时 wb_view 内部状态的快照。这包括有关加载哪些文件、如何显示、如何配置选项卡的信息(选择了哪些表面、在每个层中选择了哪些文件、打开了哪些层、哪些视图旋转、调色板设置、平铺选项卡等),以及在它们上面添加了哪些注释(文本、箭头、圆圈等)。

从事脑科学核磁共振方法学研究,在Nature communications等权威期刊发表研究论文,熟练掌握磁共振处理方法和统计学方法,欢迎大家和我交流。 3042

Java并发编程一如何关闭线程池

Java并发编程一如何关闭线程池 当线程池中已经有大量线程在处理任务,并且任务队列中也有很多任务在等待被处理,这个时候我们该如何去关闭线程池呢? 首先我们来创建一个任务。 任务 ShutDownTask类实现了Runnable接口,它的run()就是我们线程所要执行的任务,我们这里的任务非常简单,就是输出自己(当前线程)的名称,再sleep(500)即可。 class ShutDownTask i...

kaven 1614

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Java并发编程-线程池(一)

Java并发编程之线程池的使用

gdr12的专栏 1295

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java 并发编程(五)-线程池一

一、ThreadPool线程池 1、概述 线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销。进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。 线程池的优势:线程池做的工作只要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中

杀神lwz的博客 1439

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Java并发编程之线程池的使用(一)

我们在做Java&amp;nbsp;Web项目的时候,我们处理请求就是使用线程池。为什么使用线程池呢?在单线程的情况下,只有处理完一个请求之后,才会去处理下一个请求,但是在一些IO操作阻塞的过程中,CPU是空闲的状态,这个时候单线程不可能去利用CPU去处理其他请求,但是多线程就可以实现。但是使用多线程的时候,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因...

皮蛋小粥的博客 874

【Java并发编程实战】——Java线程池ThreadPoolExecutor(一)

创建或者关闭线程需要时间,且线程本身需要占用内存资源,因此生产环境线程的数量必须得到控制,盲目的创建线程对系统性能有影响

mbtlami 313

JAVA并发编程(一)——线程池

目录 java线程池的总结及线程池框架Executor的总结。

xulongyu_0617的博客 437

【并发编程】JAVA线程池(一)

并发编程、多线程、Executor、ExecutorService

cb0610的博客 151

Java并发编程——线程池的使用(一) 简单创建线程池

Java并发编程——线程池的使用

h610968110的博客 678

JAVA并发编程-线程池实现原理解读(一)

线程管理是消费者,根据任务请求进行任务分配,当线程执行完任务后会继续获取新的任务执行,当获取不到任务的时候,线程会被回收(具体细节需要参考是否是核心线程,allowCoreThreadTimeout属性等)。def:是一种池化思想管理线程的工具,因为线程过多会带来额外的开销,比如线程的创建,线程的销毁,线程的调度。线程池维护多个线程,分配可并发的任务,避免创建销毁线程带来的开销,也避免了线程过多导致的过分调度问题。1、Executor 可以将任务的提交和每个任务运行的细节(线程使用调度)解耦。

qq_51059003的博客 386

Java 并发编程之线程池的使用(一)

目录(?)[+] 在任务与执行策略之间的隐性耦合 Executor框架可以将任务的提交与任务的执行策略解耦开来(就是独立化)。虽然Executor框架为制定和修改执行策略都提供了相当大的灵活性,但并非所有的任务都能适用所有的执行策略 比如: 依赖性任务 比如依赖于执行时序,执行结果或者其他效果,那么任务就带有隐含的依赖性。此时必须小心 地维持这些执行策略以避免产生活跃性问

下雨天__的专栏 598

Java并发编程之线程池(一)

线程池 自定义线程池 步骤1:自定义拒绝策略接口 步骤2:自定义任务队列 步骤3:自定义线程池 步骤4:测试

qq_42964601的博客 154

java并发编程-线程池(一)Executor框架

如果觉得写的还可以请关注微信公众号:程序猿的日常分享,定期更新分享。 为什么需要线程池 在java中,使用线程来执行异步任务。java线程的创建与销毁需要一定的开销。如果每个任务都创建一个线程会带来哪些问题: 1、如果我们为每一个任务都创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源。同时,为每一个任务创建一个新线程来执行,这种策略可能会使处于高负荷状态的应用最终崩溃。 2、过多的线程会占用过多的内存等资源,还会带来过多的上下文切换,同时还会导致系统不稳定。 线程池解决问题思路 针

王的博客 233

java并发编程(一)-线程池

概要:对于线程理解一直的不深,这篇文章参考《java编程思想》并发这一章节的思路,稍微深入的梳理线程知识,例子来源主要是书上的练习题。不过由于原书篇幅较长,所以这篇文章主要梳理基本的线程机制这一小节。定义任务 练习一:实现一个Runnable接口。在run()内部打印一个消息,然后调用yield()。重复这个操作三次,然后从run()中返回。在构造器中放置一条启动消息,并且放置一条在任务终止时的关

geekrunner的博客 1157
上一篇: Android屏幕适配
下一篇: Android的各种Drawable详解
robert_chao
博客等级 码龄15年 265粉丝 119原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值