Java多线程并发编程

一、线程池

1.1、什么是线程池

       线程池是一种多线程的处理方式,利用已有线程对象继续服务新的任务(按照一定的执行策略),而不是频繁地创建销毁线程对象,由此提高服务的吞吐能力,减少CPU的闲置时间。具体组成部分包括:
(1)、线程池管理器(ThreadPool)用于创建和管理线程池,包括创建线程池、销毁线程池,添加新任务。
(2)、工作线程(Worker)线程池中的线程,闲置的时候处于等待状态,可以循环回收利用。
(3)、任务接口(Task)每个任务必须实现的接口类,为工作线程提供调用,主要规定了任务的入口、任务完成的收尾工作、任务的状态。
(4)、等待队列(Queue)存放等待处理的任务,提供缓冲机制。

1.2、线程池的种类

(1)、FixedThreadPool固定数量的线程池,线程池中的线程数量是固定的,不会改变。
(2)、SingleThreadExecutor单一线程池,线程池中只有一个线程。
(3)、CachedThreadPool缓存线程池,线程池中的线程数量不固定,会根据需求的大小进行改变。
(4)、ScheduledThreadPool计划任务调度的线程池,用于执行计划任务,比如每隔5分钟怎么样。

ThreadPoolExecutor构造函数中参数的含义:

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}

(1)、corePoolSize:线程池中核心线程数的数目
(2)、maximumPoolSize:线程池中最多能容纳多少个线程
(3)、keepAliveTime:当现在线程数目大于corePoolSize时,超过keepAliveTime时间后,多出corePoolSize的那些线程将被终结
(4)、unitkeepAliveTime的单位
(5)、workQueue:当任务数量很大,线程池中线程无法满足时,提交的任务会被放到阻塞队列中,线程空闲下来则会不断从阻塞队列中取数据。
(6)、threadFactory:执行程序创建新线程时使用的工厂
(7)、handler:由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序

RejectedExecutionHandler拒绝的4种策略:
(1)、AbortPolicy:如果不能接受任务了,则抛出异常。
(2)、CallerRunsPolicy:如果不能接受任务了,则让调用的线程去完成。
(3)、DiscardOldestPolicy:如果不能接受任务了,则丢弃最老的一个任务,由一个队列来维护。
(4)、DiscardPolicy:如果不能接受任务了,则丢弃任务。

1.3、携带结果的任务Callable和Future/FutureTask

(1)、Callable:解决Runnable接口不能返回一个值或受检查的异常,可以采用Callable接口实现一个任务。
(2)、Future表示异步计算的结果,可以对于具体的Runnable或者Callable任务进行查询是否完成,查询是否取消,获取执行结果,取消任务等操作。
(3)、FutureTask:是一个RunnableFuture<V>,而RunnableFuture实现了Runnbale又实现了Futrue<V>这两个接口

1.4、Fork/Join框架

       Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。
       Fork/Join类似MapReduce算法,两者区别是:Fork/Join 只有在必要时如任务非常大的情况下才分割成一个个小任务,而 MapReduce总是在开始执行第一步进行分割。看来,Fork/Join更适合一个JVM内线程级别,而MapReduce适合分布式系统

(1)、工作窃取算法

       工作窃取(work-stealing)算法是指某个线程从其他队列里窃取任务来执行。工作窃取的运行流程图如下:

       那么为什么需要使用工作窃取算法呢?
       假如我们需要做一个比较大的任务,我们可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,于是把这些子任务分别放到不同的队列里,并为每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应,比如A线程负责处理A队列里的任务。但是有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务等待处理。干完活的线程与其等着,不如去帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行
       工作窃取算法的优点充分利用线程进行并行计算,并减少了线程间的竞争,其缺点是在某些情况下还是存在竞争,比如双端队列里只有一个任务时。并且消耗了更多的系统资源,比如创建多个线程和多个双端队列。

(2)、如何设计一个Fork/Join框架?

       第一步分割任务。首先我们需要有一个fork类来把大任务分割成子任务,有可能子任务还是很大,所以还需要不停的分割,直到分割出的子任务足够小。
       第二步执行任务并合并结果。分割的子任务分别放在双端队列里,然后几个启动线程分别从双端队列里获取任务执行。子任务执行完的结果都统一放在一个队列里,启动一个线程从队列里拿数据,然后合并这些数据。

       Fork/Join使用两个类来完成以上两件事情:

       1)、ForkJoinTask:我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join()操作的机制,通常情况下我们不需要直接继承ForkJoinTask类,而只需要继承它的子类,Fork/Join框架提供了以下两个子类:
       RecursiveAction:用于没有返回结果的任务
       RecursiveTask :用于有返回结果的任务
       2)、ForkJoinPoolForkJoinTask需要通过ForkJoinPool来执行,任务分割出的子任务会添加到当前工作线程所维护的双端队列中,进入队列的头部。当一个工作线程的队列里暂时没有任务时,它会随机从其他工作线程的队列的尾部获取一个任务。

(2)、Fork/Join框架的实现原理

       ForkJoinPool由ForkJoinTask数组和ForkJoinWorkerThread数组组成,ForkJoinTask数组负责存放程序提交给ForkJoinPool的任务,而ForkJoinWorkerThread数组负责执行这些任务。
       ForkJoinTask的fork方法实现原理:当我们调用ForkJoinTask的fork方法时,程序会调用ForkJoinWorkerThread的pushTask方法异步的执行这个任务,然后立即返回结果。pushTask方法把当前任务存放在ForkJoinTask 数组queue里。然后再调用ForkJoinPool的signalWork()方法唤醒或创建一个工作线程来执行任务。
       ForkJoinTask的join方法实现原理:Join方法的主要作用是阻塞当前线程并等待获取结果

(4)、Fork/Join框架的异常处理

       ForkJoinTask在执行的时候可能会抛出异常,但是我们没办法在主线程里直接捕获异常,所以ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法获取异常。

二、JDK并发包

2.1、同步控制工具类

(1)、Semaphore

       计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。是一个共享锁,允许N个线程同时进入临界区, 但是超出许可范围的只能等待;如果N = 1, 则类似于lock

(2)、ReentrantLock

       简而言之, 就是自由度更高的synchronized, 主要具备以下优点
       可重入:单线程可以重复进入,但要重复退出
       可中断:lock.lockInterruptibly()
       可限时:超时不能获得锁,就返回false,不会永久等待构成死锁
       公平锁:先来先得,public ReentrantLock(boolean fair),默认锁不公平的, 根据线程优先级竞争

(3)、Condition

       类似于 Object.wait()和Object.notify(), 需要与ReentrantLock结合使用.

(4)、ReadWriteLock

       读写分离锁, 可以大幅提升系统并行度.
       读-读不互斥:读读之间不阻塞。
       读-写互斥:读阻塞写,写也会阻塞读。
       写-写互斥:写写阻塞。

(5)、CountDownLatch倒数计时器

       一种典型的场景就是火箭发射。在火箭发射前,为了保证万无一失,往往还要进行各项设备、仪器的检查。
只有等所有检查完毕后,引擎才能点火。这种场景就非常适合使用CountDownLatch。它可以使得点火线程, 
等待所有检查线程全部完工后,再执行

(6)、CyclicBarrier循环栅栏

       Cyclic意为循环,也就是说这个计数器可以反复使用。比如,假设我们将计数器设置为10。那么凑齐
第一批10个线程后,计数器就会归零,然后接着凑齐下一批10个线程

(7)、LockSupport

       一个线程阻塞工具, 可以在任意位置让线程阻塞。与wait/notify比较,如果unpark发生在park之前, 并不会导致线程冻结,也不需要获取锁
       LockSupport比Object的wait/notify有两大优势:
       1)、LockSupport不需要在同步代码块里 。所以线程间也不需要维护一个共享的同步对象了,实现了线程间的解耦
       2)、unpark函数可以先于park调用,所以不需要担心线程间的执行的先后顺序

2.2、并发容器

(1)、Collections.synchronizedMap

       其本质是在读写map操作上都加了锁,因此不推荐在高并发场景使用

(2)、ConcurrentHashMap
       内部使用分区Segment来表示不同的部分, 每个分区其实就是一个小的hashtable,各自有自己的锁,只要多个修改发生在不同的分区,他们就可以并发的进行。把一个整体分成了16个Segment,最高支持16个线程并发修改

(3)、BlockingQueue

       阻塞队列, 主要用于多线程之间共享数据;当一个线程读取数据时,如果队列是空的,则当前线程会进入等待状态;如果队列满了,当一个线程尝试写入数据时,同样会进入等待状态;适用于生产消费者模型,因为BlockingQueue在put、take等操作有锁,因此非高性能容器;如果需要高并发支持的队列,则可以使用ConcurrentLinkedQueue,他内部运用了大量无锁操作

(4)、CopyOnWriteArrayList

       CopyOnWriteArrayList通过在新增元素时,复制一份新的数组出来,并在其中写入数据,之后将原数组引用指向到新数组,其Add操作是在内部通过ReentrantLock进行锁保护,防止多线程场景复制多份数组,而Read操作内部无锁,直接返回数组引用,并发下效率高,因此适用于读多写少的场景

参考文章:

(1)、Java多线程并发编程一览笔录

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480982.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Step-by-step to Transformer:深入解析工作原理(以Pytorch机器翻译为例)

大家好&#xff0c;我是青青山螺应如是&#xff0c;大家可以叫我青青&#xff0c;工作之余是一名独立摄影师。喜欢美食、旅行、看展&#xff0c;偶尔整理下NLP学习笔记&#xff0c;不管技术文还是生活随感&#xff0c;都会分享本人摄影作品&#xff0c;希望文艺的技术青年能够喜…

知识图谱与智能问答基础理解

什么是知识图谱&#xff1f; 知识图谱本质上是语义网络&#xff0c;是一种基于图的数据结构&#xff0c;由节点(Point)和边(Edge)组成。在知识图谱里&#xff0c;每个节点表示现实世界中存在的“实体”&#xff0c;每条边为实体与实体之间的“关系”。知识图谱是关系的最有效的…

鲍捷 | 知识图谱从 0 级到 10 级简化版

本文转载自公众号&#xff1a;文因学堂。文因学以前写过几个进阶指南&#xff0c;可能都太难&#xff0c;不接地气。这里重新写一个更实事求是、更便于工程落地的版本0级&#xff1a;掌握正则表达式、SQL、JSON和一门支持if-then-else的高级语言 —— 是的&#xff0c;这些不是…

Java并发优化思路

一、并发优化 1.1、Java高并发包所采用的几个机制 &#xff08;1&#xff09;、CAS&#xff08;乐观操作&#xff09; jdk5以前采用synchronized&#xff0c;对共享区域进行同步操作&#xff0c;synchronized是重的操作&#xff0c;在高并发情况下&#xff0c;会引起线…

他与她,一个两年前的故事

“ 有没有那个Ta&#xff0c;值得你一生去守护”1她能力出众&#xff0c;业务能力无人能出其左右&#xff1b;他资质平庸&#xff0c;扮演一个很不起眼的角色&#xff1b;她国色天香&#xff0c;是整个公司上上下下关注的焦点&#xff1b;他其貌不扬&#xff0c;甚至很多人根本…

科普 | 知识图谱相关的名词解释

知识图谱&#xff08;Knowledge Graph&#xff09;是谷歌于2012年提出。企业通常出于商业目的去设计新的概念和名词。但每一个概念的提出都有其历史渊源和本质内涵。下面列举了知识图谱相关的几个概念&#xff0c;并简要阐明了它们与知识图谱的关系和区别。Knowledge Base&…

搜索引擎核心技术与算法 —— 倒排索引初体验

今天开启一个新篇章——智能搜索与NLP。本篇章将由羸弱菜鸡小Q和大家一同学习与智能搜索相关的知识和技术&#xff0c;希望能和大家一同学习与进步&#xff0c;冲鸭&#xff01;&#xff01;这里首先区分两个概念&#xff1a;搜索和检索检索&#xff1a;数据库时代的概念&#…

微服务设计原则和解决方案

一、微服务架构演进过程 近年来我们大家都体会到了互联网、移动互联带来的好处&#xff0c;作为IT从业者&#xff0c;在生活中时刻感受互联网好处的同时&#xff0c;在工作中可能感受的却是来自自互联网的一些压力&#xff0c;那就是我们传统企业的IT建设也是迫切需要转型&…

技术动态 | 知识可视化,连接和探究知识之间的联系!

本文转载自公众号&#xff1a;东湖大数据交易中心。大数据百人会线上沙龙 第八期3月1日晚八点&#xff0c;大数据百人会沙龙第八期主讲嘉宾——北京知珠传媒科技有限公司CEO郝庆一先生&#xff0c;分享他对可视化的理解&#xff0c;以及连接知识、探究知识之间的关系。1可视化…

潜在语义分析原理以及python实现代码!!!!

在Wiki上看到的LSA的详细介绍&#xff0c;感觉挺好的&#xff0c;遂翻译过来&#xff0c;有翻译不对之处还望指教。 原文地址&#xff1a;http://en.wikipedia.org/wiki/Latent_semantic_analysis 前言 浅层语义分析&#xff08;LSA&#xff09;是一种自然语言处理中用到的方法…

史上最可爱的关系抽取指南?从一条规则到十个开源项目

正文来自订阅号&#xff1a;AINLP正文作者&#xff1a;太子長琴&#xff08;NLP算法工程师&#xff09;小夕&#xff0c;我来给你出个题&#xff0c;看看你的反应如何&#xff1f;好呀好呀&#xff0c;你说~“梁启超有一个著名的儿子&#xff0c;叫梁思成;同时还有一个著名的学…

论文浅尝 | Leveraging Knowledge Bases in LSTMs

Yang, B., Mitchell, T., 2017. Leveraging Knowledge Bases in LSTMs for Improving Machine Reading. Association for Computational Linguistics, pp. 1436–1446.链接&#xff1a;http://www.aclweb.org/anthology/P/P17/P17-1132.pdf这篇论文是今年发表在 ACL 的一篇文章…

支付系统-对账系统

在支付系统中&#xff0c;资金对账在对账中心进行&#xff0c;将系统保存的账务流水与银行返回的清算流水和清算文件进行对账&#xff0c;核对系统账务数据与银行清算数据的一致性&#xff0c;保证支付机构各备付金银行账户每日的预计发生额与实际发生额一致。 一、清算对账系…

在线GPU分布式实验环境+企业级项目,轻松斩获offer

人工智能微专业招生简章&#xff08;春季&#xff09;重构专业核心培养复合型人才与斯坦福、伯克利、MIT、清华Top10名校同学成为校友一对一学习与职业规划扫码立刻加入本季招生名额仅剩200人

支付系统-系统架构

本文主要是从支付架构、支付流程分析、支付核心逻辑、支付基础服务、支付安全五个方面来详细讲述支付系统架构 &#xff08;1&#xff09;、架构的定义&#xff1a;架构一定是基于业务功能来展开的&#xff0c;主要是制定技术规范、框架&#xff0c;指导系统落地&#xff1b;好…

领域应用 | 智能导购?你只看到了阿里知识图谱冰山一角

在刚刚结束的2017第四届世界互联网大会上&#xff0c;评选出了年度18项代表性的领先科技成果&#xff0c;阿里云ET大脑就是其中之一。众所周知&#xff0c;融合了先进的大数据、人工智能技术的阿里云ET大脑已经在智慧城市、智慧交通等众多领域得到了应用和推广。但你知不知道&a…

美团技术团队-大众点评搜索基于知识图谱的深度学习排序实践

美团技术团队博客网址&#xff1a;https://tech.meituan.com/2019/02/28/root-clause-analysis.html 1. 引言挑战与思路搜索是大众点评App上用户进行信息查找的最大入口&#xff0c;是连接用户和信息的重要纽带。而用户搜索的方式和场景非常多样&#xff0c;并且由于对接业务种…

NLP、炼丹技巧和基础理论文章索引

玩家你好 恭喜你捡到了一个来自上古时期的*七*星*炼*丹*炉*&#xff0c;只见炉壁上镶嵌着自然语言处理、推荐系统、信息检索、深度炼丹、机器学习、数学与基础算法等失传已久的江湖秘术。熔炉中虽然已有一层厚厚尘土&#xff0c;却依然掩盖不住尘埃下那一颗颗躁动不安的仙丹。 …

支付系统-概念与架构

一、什么是支付系统 自古以来&#xff0c;所有的商业活动都会产生货币的收款与付款行为。在人类漫长的历史长河中&#xff0c;记录收付款行为的方式不断迭代&#xff1a;古代的账房先生通过手工记账&#xff0c;工业社会通过收银机机械记账…… 今天&#xff0c;进入了互…

论文浅尝 | Reinforcement Learning for Relation Classification

论文链接&#xff1a;http://aihuang.org/p/papers/AAAI2018Denoising.pdf来源&#xff1a;AAAI 2018MotivationDistant Supervision 是一种常用的生成关系分类训练样本的方法&#xff0c;它通过将知识库与非结构化文本对齐来自动构建大量训练样本&#xff0c;减少模型对人工标…