
Java并发
Java并发编程
gqltt
这个作者很懒,什么都没留下…
展开
-
CompletableFuture详解~异步发起然后...
【代码】CompletableFuture详解~异步发起然后...原创 2023-06-29 12:08:47 · 226 阅读 · 0 评论 -
CompletableFuture详解~思维导图
#原图System.out.println("https://www.processon.com/view/621a1b361e08533fc3afaa44?fromnew=1");原创 2022-03-06 18:22:09 · 472 阅读 · 0 评论 -
CompletableFuture详解~join与get的区别
一.相同点:join()和get()方法都是用来获取CompletableFuture异步之后的返回值二.区别:1.join()方法抛出的是uncheck异常(即RuntimeException),不会强制开发者抛出, 会将异常包装成CompletionException异常 /CancellationException异常,但是本质原因还是代码内存在的真正的异常, public static void main(String[] args) { Compl原创 2022-02-28 11:36:09 · 26757 阅读 · 0 评论 -
CompletableFuture详解~异常处理
计算结果完成时的回调方法当 CompletableFuture 的计算结果完成,或者抛出异常的时候,可以执行特定的 Action。主要是下面的方法:public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,原创 2022-02-28 11:12:16 · 9351 阅读 · 0 评论 -
CompletableFuture详解~supplyAsync
supplyAsync 可以支持返回值。//有返回值public static void supplyAsync() throws Exception { CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException原创 2022-02-28 11:07:26 · 1182 阅读 · 0 评论 -
CompletableFuture详解~allOf
当所有的阶段都完成后创建一个阶段上一个例子是当任意一个阶段完成后接着处理,接下来的两个例子演示当所有的阶段完成后才继续处理, 同步地方式和异步地方式两种。static void allOfExample() { StringBuilder result = new StringBuilder(); List messages = Arrays.asList("a", "b", "c"); List<CompletableFuture> futures = mes原创 2022-02-28 10:01:32 · 47806 阅读 · 0 评论 -
CompletableFuture详解~anyOf
当几个阶段中的一个完成,创建一个完成的阶段下面的例子演示了当任意一个CompletableFuture完成后, 创建一个完成的CompletableFuture.待处理的阶段首先创建, 每个阶段都是转换一个字符串为大写。因为本例中这些阶段都是同步地执行(thenApply), 从anyOf中创建的CompletableFuture会立即完成,这样所有的阶段都已完成,我们使用whenComplete(BiConsumer<? super Object, ? super Throwable>原创 2022-02-28 09:54:20 · 2260 阅读 · 0 评论 -
CompletableFuture详解~thenCompose
组合 CompletableFuture我们可以使用thenCompose()完成上面两个例子。这个方法等待第一个阶段的完成(大写转换), 它的结果传给一个指定的返回CompletableFuture函数,它的结果就是返回的CompletableFuture的结果。有点拗口,但是我们看例子来理解。函数需要一个大写字符串做参数,然后返回一个CompletableFuture, 这个CompletableFuture会转换字符串变成小写然后连接在大写字符串的后面。static void thenC原创 2022-02-28 09:51:46 · 1399 阅读 · 0 评论 -
CompletableFuture详解~thenCombine
使用BiFunction处理两个阶段的结果如果CompletableFuture依赖两个前面阶段的结果, 它复合两个阶段的结果再返回一个结果,我们就可以使用thenCombine()函数。整个流水线是同步的,所以getNow()会得到最终的结果,它把大写和小写字符串连接起来。static void thenCombineExample() { String original = "Message"; CompletableFuture cf = CompletableFuture.原创 2022-02-28 09:36:00 · 4107 阅读 · 0 评论 -
CompletableFuture详解~thenAcceptBoth
使用BiConsumer处理两个阶段的结果上面的例子还可以通过BiConsumer来实现:static void thenAcceptBothExample() { String original = "Message"; StringBuilder result = new StringBuilder(); CompletableFuture.completedFuture(original).thenApply(String::toUpperCase).thenAcce原创 2022-02-28 09:34:11 · 1004 阅读 · 0 评论 -
CompletableFuture详解~runAfterBoth
这个例子演示了依赖的CompletableFuture如果等待两个阶段完成后执行了一个Runnable。注意下面所有的阶段都是同步执行的,第一个阶段执行大写转换,第二个阶段执行小写转换static void runAfterBothExample() { String original = "Message"; StringBuilder result = new StringBuilder(); CompletableFuture.completedFuture(origin原创 2022-02-28 09:31:47 · 754 阅读 · 0 评论 -
CompletableFuture详解~acceptEither
在两个完成的阶段其中之一上调用消费函数和前一个例子很类似了,只不过我们调用的是消费者函数 (Function变成Consumer):static void acceptEitherExample() { String original = "Message"; StringBuilder result = new StringBuilder(); CompletableFuture cf = CompletableFuture.completedFuture(origina原创 2022-02-28 09:27:35 · 387 阅读 · 0 评论 -
CompletableFuture详解~applyToEither
在两个完成的阶段其中之一上应用函数下面的例子创建了CompletableFuture, applyToEither处理两个阶段, 在其中之一上应用函数(包保证哪一个被执行)。本例中的两个阶段一个是应用大写转换在原始的字符串上, 另一个阶段是应用小些转换。static void applyToEitherExample() { String original = "Message"; CompletableFuture cf1 = CompletableFuture.complete原创 2022-02-27 18:55:17 · 878 阅读 · 0 评论 -
CompletableFuture详解~cancel
取消计算和完成异常类似,我们可以调用cancel(boolean mayInterruptIfRunning)取消计算。对于CompletableFuture类,布尔参数并没有被使用,这是因为它并没有使用中断去取消操作,相反,cancel等价于completeExceptionally(new CancellationException())。static void cancelExample() { CompletableFuture cf = CompletableFuture.com原创 2022-02-27 18:50:12 · 2812 阅读 · 0 评论 -
CompletableFuture详解~completeExpectionally
完成计算异常现在我们来看一下异步操作如何显式地返回异常,用来指示计算失败。我们简化这个例子,操作处理一个字符串,把它转换成答谢,我们模拟延迟一秒。我们使用thenApplyAsync(Function, Executor)方法,第一个参数传入大写函数, executor是一个delayed executor,在执行前会延迟一秒。static void completeExceptionallyExample() { CompletableFuture cf = CompletableF原创 2022-02-27 18:47:42 · 4179 阅读 · 0 评论 -
CompletableFuture详解~thenAcceptAsync
异步地消费迁移阶段的结果同样,可以使用thenAcceptAsync方法, 串联的CompletableFuture可以异步地执行。static void thenAcceptAsyncExample() { StringBuilder result = new StringBuilder(); CompletableFuture cf = CompletableFuture.completedFuture("thenAcceptAsync message")原创 2022-02-27 18:40:16 · 3361 阅读 · 0 评论 -
CompletableFuture详解~thenAccept
消费前一阶段的结果如果下一阶段接收了当前阶段的结果,但是在计算的时候不需要返回值(它的返回类型是void), 那么它可以不应用一个函数,而是一个消费者, 调用方法也变成了thenAccept:static void thenAcceptExample() { StringBuilder result = new StringBuilder(); CompletableFuture.completedFuture("thenAccept message") .原创 2022-02-27 18:37:24 · 3156 阅读 · 0 评论 -
CompletableFuture详解~thenApplyAsync
通过调用异步方法(方法后边加Async后缀),串联起来的CompletableFuture可以异步地执行(使用ForkJoinPool.commonPool())。static void thenApplyAsyncExample() { CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> { assertTrue(Thread.currentThr原创 2022-02-27 18:34:52 · 2563 阅读 · 0 评论 -
CompletableFuture详解~thenApply
下面这个例子使用前面 #1 的完成的CompletableFuture, #1返回结果为字符串message,然后应用一个函数把它变成大写字母。static void thenApplyExample() { CompletableFuture cf = CompletableFuture.completedFuture("message").thenApply(s -> { assertFalse(Thread.currentThread().isDaemon());原创 2022-02-27 18:32:40 · 2972 阅读 · 0 评论 -
CompletableFuture详解~runAsync
这个例子创建一个一个异步执行的阶段:static void runAsyncExample() { CompletableFuture cf = CompletableFuture.runAsync(() -> { assertTrue(Thread.currentThread().isDaemon()); randomSleep(); }); assertFalse(cf.isDone()); sleepEnough();原创 2022-02-27 18:27:35 · 31945 阅读 · 0 评论 -
CompletableFuture详解~getNow
最简单的例子就是使用一个预定义的结果创建一个完成的CompletableFuture,通常我们会在计算的开始阶段使用它。static void completedFutureExample() { CompletableFuture cf = CompletableFuture.completedFuture("message"); assertTrue(cf.isDone()); assertEquals("message", cf.getNow(null));}get原创 2022-02-27 18:24:43 · 1985 阅读 · 0 评论 -
CompletableFuture详解~CompletionStage
CompletableFuture 分别实现两个接口 Future与 CompletionStage。Future 接口大家都比较熟悉,这里主要讲讲 CompletionStage。CompletableFuture 大部分方法来自CompletionStage 接口,正是因为这个接口,CompletableFuture才有如此强大功能。想要理解 CompletionStage 接口,我们需要先了解任务的时序关系的。我们可以将任务时序关系分为以下几种: 串行执行关系 并行原创 2022-02-26 21:58:39 · 1524 阅读 · 0 评论 -
CompletableFuture详解~设置任务结果
CompletableFuture 提供以下方法,可以主动设置任务结果。boolean complete(T value)boolean completeExceptionally(Throwable ex)第一个方法,主动设置 CompletableFuture 任务执行结果,若返回 true,表示设置成功。如果返回 false,设置失败,这是因为任务已经执行结束,已经有了执行结果。示例代码如下:// 执行异步任务CompletableFuture cf = Completabl原创 2022-02-26 20:56:47 · 1097 阅读 · 0 评论 -
CompletableFuture详解~创建实例
创建 CompletableFuture 对象实例我们可以使用如下几个方法:static CompletableFuture<U> completedFuture(U value)//使用forkjoin公共线程池static CompletableFuture<Void> runAsync(Runnable runnable)static CompletableFuture<U> supplyAsync(Supplier<U> supplier原创 2022-02-26 20:53:17 · 856 阅读 · 0 评论 -
Java并发编程实战~协程
Golang 是一门号称从语言层面支持并发的编程语言,支持并发是 Golang 一个非常重要的特性。在上一篇文章《44 | 协程:更轻量级的线程》中我们介绍过,Golang 支持协程,协程可以类比 Java 中的线程,解决并发问题的难点就在于线程(协程)之间的协作。那 Golang 是如何解决协作问题的呢?总的来说,Golang 提供了两种不同的方案:一种方案支持协程之间以共享内存的方式通信,Golang 提供了管程和原子类来对协程进行同步控制,这个方案与 Java 语言类似;另一种方案支持协程之间转载 2021-11-29 14:38:23 · 280 阅读 · 0 评论 -
Java并发编程实战~协程
Java 语言里解决并发问题靠的是多线程,但线程是个重量级的对象,不能频繁创建、销毁,而且线程切换的成本也很高,为了解决这些问题,Java SDK 提供了线程池。然而用好线程池并不容易,Java 围绕线程池提供了很多工具类,这些工具类学起来也不容易。那有没有更好的解决方案呢?Java 语言里目前还没有,但是其他语言里有,这个方案就是协程(Coroutine)。我们可以把协程简单地理解为一种轻量级的线程。从操作系统的角度来看,线程是在内核态中调度的,而协程是在用户态调度的,所以相对于线程来说,协程切换的成转载 2021-11-29 14:36:31 · 652 阅读 · 0 评论 -
Java并发编程实战~软件事务内存
很多同学反馈说,工作了挺长时间但是没有机会接触并发编程,实际上我们天天都在写并发程序,只不过并发相关的问题都被类似 Tomcat 这样的 Web 服务器以及 MySQL 这样的数据库解决了。尤其是数据库,在解决并发问题方面,可谓成绩斐然,它的事务机制非常简单易用,能甩 Java 里面的锁、原子类十条街。技术无边界,很显然要借鉴一下。其实很多编程语言都有从数据库的事务管理中获得灵感,并且总结出了一个新的并发解决方案:软件事务内存(Software Transactional Memory,简称 STM)。传转载 2021-11-29 14:34:39 · 407 阅读 · 0 评论 -
Java并发编程实战~线程池创建
import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.RejectedExecutionHandler;import java.util.concurrent.ThreadFactory;import java.util.concurrent.ThreadPool...原创 2021-11-29 11:44:26 · 368 阅读 · 0 评论 -
Exchanger及其用法
01 Exchanger 作用使两个线程之间进行数据传递。(对是两个之间而不是三个或者更多个线程之间)02 常用方法exchange()阻塞当前线程并等待其他线程来取得数据,若没有其他线程来取数据则一直等待。exchange()传递数据exchange(V v, long timeout, TimeUnit unit)在指定的时间内没收到消息,则抛出超时的异常。Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供...原创 2021-11-29 09:49:57 · 637 阅读 · 0 评论 -
Semaphore及其用法
1、Semaphore 是什么Semaphore 通常我们叫它信号量, 可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。可以把它简单的理解成我们停车场入口立着的那个显示屏,每有一辆车进入停车场显示屏就会显示剩余车位减1,每有一辆车从停车场出去,显示屏上显示的剩余车辆就会加1,当显示屏上的剩余车位为0时,停车场入口的栏杆就不会再打开,车辆就无法进入停车场了,直到有一辆车从停车场出去为止。2、使用场景通常用于那些资源有明确访问数量限制的场景,常用于限流 。转载 2021-11-29 08:58:25 · 4772 阅读 · 1 评论 -
Java并发编程实战~软件事务内存
很多同学反馈说,工作了挺长时间但是没有机会接触并发编程,实际上我们天天都在写并发程序,只不过并发相关的问题都被类似 Tomcat 这样的 Web 服务器以及 MySQL 这样的数据库解决了。尤其是数据库,在解决并发问题方面,可谓成绩斐然,它的事务机制非常简单易用,能甩 Java 里面的锁、原子类十条街。技术无边界,很显然要借鉴一下。其实很多编程语言都有从数据库的事务管理中获得灵感,并且总结出了一个新的并发解决方案:软件事务内存(Software Transactional Memory,简称 STM)。传转载 2021-11-28 20:16:17 · 176 阅读 · 0 评论 -
Java并发编程实战~Actor 模型
Hello Actor 模型Actor 模型本质上是一种计算模型,基本的计算单元称为 Actor,换言之,在 Actor 模型中,所有的计算都是在 Actor 中执行的。在面向对象编程里面,一切都是对象;在 Actor 模型里,一切都是 Actor,并且 Actor 之间是完全隔离的,不会共享任何变量。当看到“不共享任何变量”的时候,相信你一定会眼前一亮,并发问题的根源就在于共享变量,而 Actor 模型中 Actor 之间不共享变量,那用 Actor 模型解决并发问题,一定是相当顺手。的确是这样,转载 2021-11-28 20:04:09 · 1629 阅读 · 0 评论 -
Java并发编程实战~生产者-消费者模式
前面我们在《Worker Thread 模式》中讲到,Worker Thread 模式类比的是工厂里车间工人的工作模式。但其实在现实世界,工厂里还有一种流水线的工作模式,类比到编程领域,就是生产者 - 消费者模式。生产者 - 消费者模式在编程领域的应用也非常广泛,前面我们曾经提到,Java 线程池本质上就是用生产者 - 消费者模式实现的,所以每当使用线程池的时候,其实就是在应用生产者 - 消费者模式。当然,除了在线程池中的应用,为了提升性能,并发编程领域很多地方也都用到了生产者 - 消费者模式,例如转载 2021-11-28 19:51:34 · 584 阅读 · 0 评论 -
Java并发编程实战~Thread-Per-Message模式
我们曾经把并发编程领域的问题总结为三个核心问题:分工、同步和互斥。其中,同步和互斥相关问题更多地源自微观,而分工问题则是源自宏观。我们解决问题,往往都是从宏观入手,在编程领域,软件的设计过程也是先从概要设计开始,而后才进行详细设计。同样,解决并发编程问题,首要问题也是解决宏观的分工问题。并发编程领域里,解决分工问题也有一系列的设计模式,比较常用的主要有 Thread-Per-Message 模式、Worker Thread 模式、生产者 - 消费者模式等等。今天我们重点介绍 Thread-Per-Mes转载 2021-11-28 19:34:39 · 169 阅读 · 0 评论 -
Java并发编程实战~Balking模式
上一篇文章中,我们提到可以用“多线程版本的 if”来理解 Guarded Suspension 模式,不同于单线程中的 if,这个“多线程版本的 if”是需要等待的,而且还很执着,必须要等到条件为真。但很显然这个世界,不是所有场景都需要这么执着,有时候我们还需要快速放弃。需要快速放弃的一个最常见的例子是各种编辑器提供的自动保存功能。自动保存功能的实现逻辑一般都是隔一定时间自动执行存盘操作,存盘操作的前提是文件做过修改,如果文件没有执行过修改操作,就需要快速放弃存盘操作。下面的示例代码将自动保存功能代码化转载 2021-11-28 19:31:56 · 144 阅读 · 0 评论 -
Java并发编程实战~Worker Thread模式
在上一篇文章中,我们介绍了一种最简单的分工模式——Thread-Per-Message 模式,对应到现实世界,其实就是委托代办。这种分工模式如果用 Java Thread 实现,频繁地创建、销毁线程非常影响性能,同时无限制地创建线程还可能导致 OOM,所以在 Java 领域使用场景就受限了。要想有效避免线程的频繁创建、销毁以及 OOM 问题,就不得不提今天我们要细聊的,也是 Java 领域使用最多的 Worker Thread 模式。Worker Thread 模式及其实现Worker Threa转载 2021-11-28 19:23:08 · 303 阅读 · 0 评论 -
Java并发编程实战~Guarded Suspension模式
Guarded Suspension 模式比如,项目组团建要外出聚餐,我们提前预订了一个包间,然后兴冲冲地奔过去,到那儿后大堂经理看了一眼包间,发现服务员正在收拾,就会告诉我们:“您预订的包间服务员正在收拾,请您稍等片刻。”过了一会,大堂经理发现包间已经收拾完了,于是马上带我们去包间就餐。那我们来看看现实世界里是如何解决这类问题的呢?现实世界里大堂经理这个角色很重要,我们是否等待,完全是由他来协调的。通过类比,相信你也一定有思路了:我们的程序里,也需要这样一个大堂经理...原创 2021-11-28 11:42:09 · 250 阅读 · 0 评论 -
Java并发编程实战~ThreadLocal
ThreadLocal 的使用方法static class SafeDateFormat { // 定义 ThreadLocal 变量 static final ThreadLocal<DateFormat>tl = ThreadLocal.withInitial(()-> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); static DateFormat get(){ return tl.get(); }}// 不同原创 2021-11-28 11:13:08 · 450 阅读 · 0 评论 -
Java并发编程实战~Copy-on-Write模式
Copy-on-Write 模式的应用领域1、在操作系统领域。类 Unix 的操作系统中创建进程的 API 是 fork(),传统的 fork() 函数会创建父进程的一个完整副本2、很多文件系统也同样用到了,例如 Btrfs (B-Tree File System)、aufs(advanced multi-layered unification filesystem)等。3、Docker 容器镜像的设计是 Copy-on-Write4、分布式源码管理系统 Git 背后的设计思想都有 Copy原创 2021-11-28 10:47:41 · 312 阅读 · 0 评论 -
Java并发编程实战~Immutability模式
解决并发问题,其实最简单的办法就是让共享变量只有读操作,而没有写操作。这个办法如此重要,以至于被上升到了一种解决并发问题的设计模式:不变性(Immutability)模式。所谓不变性,简单来讲,就是对象一旦被创建之后,状态就不再发生变化。换句话说,就是变量一旦被赋值,就不允许修改了(没有写操作);没有修改操作,也就是保持了不变性。快速实现具备不可变性的类将一个类所有的属性都设置成 final 的,并且只允许存在只读方法,那么这个类基本上就具备不可变性了。更严格的做...原创 2021-11-28 10:36:36 · 261 阅读 · 0 评论