Exchanger交换空间

如果现在有两个线程,一个线程负责生产数据,另外一个线程负责消费数据,那么这个两个线程之间一定会存在一个公共的区域,那么这个区域的实现在JUC包之中称为Exchanger

java.util.concurrent.Exchanger类表示一种两个线程可以进行互相交换对象的汇合点。

Exchanger类中定义的方法如下:

  • 构造方法:

    pubilc Exchanger();  //创建一个对象
  • 设置与取得:
    public V exchange(V x) throws InterruptedException

范例:使用Exchanger实现交换处理

package so.strong.mall.concurrent;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit; public class ExchanerDemo {
public static void main(String[] args) {
final Exchanger<String> exchanger = new Exchanger<>(); //准备一个交换空间
for (int i = 0; i < 3; i++) { //3个消费者
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
String data = exchanger.exchange(null);
TimeUnit.SECONDS.sleep(2);
if (data != null) {
System.out.println("[" + Thread.currentThread().getName() + "]取得数据:" + data);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "消费者-" + i).start();
} for (int i = 0; i < 2; i++) { //2个生产者
final int temp = i;
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 2; j++) {
String data = "iTermis-" + temp + "-" + j;
try {
TimeUnit.SECONDS.sleep(2); //让生产者节奏放慢
exchanger.exchange(data);
System.out.println("[" + Thread.currentThread().getName() + "]生产了数据:" + data);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, "生产者-" + i).start();
}
}
}
[生产者-1]生产了数据:iTermis-1-0
[生产者-1]生产了数据:iTermis-1-1
[消费者-1]取得数据:iTermis-1-0
[生产者-0]生产了数据:iTermis-0-0
[生产者-0]生产了数据:iTermis-0-1
[消费者-2]取得数据:iTermis-0-1

  

CompletableFuture线程回调

现在设想一个场景,例如:使用炮兵轰炸某一目标

所有的执行线程在接收到命令之前都要进入到阻塞状态之中,一直到接收到具体的命令之后才会执行下一步操作处理。

java.util.concurrent.CompletableFutureJava8中添加的一个类,该类的主要作用是提供了新的方式来完成异步处理,包括合成和组合事件的非阻塞方式。

CompletableFuture类中有如下的方法:

  • 构造方法:

    public CompletableFuture();
  • 获取命令:
    public T get() throws InterruptedException,ExecutionException  

范例:使用CompletableFuture实现炮兵轰炸操作

package com.itermis.concurrent;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; public class CompletableFutureDemo {
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = new CompletableFuture<>();
for (int i = 0; i < 4; i++) {
new Thread(() -> {
System.out.println("BEFORE[" + Thread.currentThread().getName() + "]进入炮兵阵地,等待命令,准备开火。");
try {
String cmd = future.get(); //接收命令
if ("fire".equals(cmd)) {
System.out.println("AFTER[" + Thread.currentThread().getName() + "]接收到命令,立刻开火,干死那个死胖子。。");
}
if ("cancel".equals(cmd)) {
System.out.println("AFTER[" + Thread.currentThread().getName() + "]收到撤退命令,回家睡觉。。");
}
} catch (Exception e) {
e.printStackTrace();
}
}, "炮兵-" + i).start();
}
TimeUnit.SECONDS.sleep(3); //等待3秒钟
future.complete("cancel"); //给出了执行命令
}
}
BEFORE[炮兵-1]进入炮兵阵地,等待命令,准备开火。
BEFORE[炮兵-0]进入炮兵阵地,等待命令,准备开火。
BEFORE[炮兵-2]进入炮兵阵地,等待命令,准备开火。
BEFORE[炮兵-3]进入炮兵阵地,等待命令,准备开火。
//sleep 3 秒
AFTER[炮兵-1]收到撤退命令,回家睡觉。。
AFTER[炮兵-0]收到撤退命令,回家睡觉。。
AFTER[炮兵-2]收到撤退命令,回家睡觉。。
AFTER[炮兵-3]收到撤退命令,回家睡觉。。

该类的处理主要是建立在Future线程模型的基础之上的实现操作。

对于本类而言,除了以上的使用方式之外还可以采用异步的线程执行方式处理。在创建CompletableFuture类对象的时候还可以使用这个类之中提供的一种静态方法:

public static CompletableFuture<Void> runAsync(Runnable runnable)

范例:更换实现方式实现上述轰炸操作:

package com.itermis.concurrent;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; public class CompletableFutureDemoII {
public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("[FUTURE]将军正在温柔乡里美梦了,等着将军睡醒开炮..");
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("[FUTURE]将军醒了,开始干活了..");
});
for (int i = 0; i < 4; i++) {
new Thread(() -> {
System.out.println("BEFORE[" + Thread.currentThread().getName() + "]进入炮兵阵地,等待命令,准备开火。");
try {
System.out.println("AFTER[" + Thread.currentThread().getName() + "]接收到命令,立刻开火,干死那个死胖子。。" + future.get());
} catch (Exception e) {
e.printStackTrace();
}
}, "炮兵-" + i).start();
}
}
}
[FUTURE]将军正在温柔乡里美梦了,等着将军睡醒开炮..
BEFORE[炮兵-1]进入炮兵阵地,等待命令,准备开火。
BEFORE[炮兵-0]进入炮兵阵地,等待命令,准备开火。
BEFORE[炮兵-2]进入炮兵阵地,等待命令,准备开火。
BEFORE[炮兵-3]进入炮兵阵地,等待命令,准备开火。
// sleep 3秒
[FUTURE]将军醒了,开始干活了..
AFTER[炮兵-2]接收到命令,立刻开火,干死那个死胖子。。null
AFTER[炮兵-0]接收到命令,立刻开火,干死那个死胖子。。null
AFTER[炮兵-3]接收到命令,立刻开火,干死那个死胖子。。null
AFTER[炮兵-1]接收到命令,立刻开火,干死那个死胖子。。null

CompletableFuture这个类最大的好处是提供有所有等待线程的执行触发点。

JUC——线程同步辅助工具类(Exchanger,CompletableFuture)的更多相关文章

  1. JUC——线程同步辅助工具类(Semaphore,CountDownLatch,CyclicBarrier)

    锁的机制从整体的运行转态来讲核心就是:阻塞,解除阻塞,但是如果仅仅是这点功能,那么JUC并不能称为一个优秀的线程开发框架,然而是因为在juc里面提供了大量方便的同步工具辅助类. Semaphore信号 ...

  2. Java并发编程系列-(2) 线程的并发工具类

    2.线程的并发工具类 2.1 Fork-Join JDK 7中引入了fork-join框架,专门来解决计算密集型的任务.可以将一个大任务,拆分成若干个小任务,如下图所示: Fork-Join框架利用了 ...

  3. Java线程的并发工具类

    Java线程的并发工具类. 一.fork/join 1. Fork-Join原理 在必要的情况下,将一个大任务,拆分(fork)成若干个小任务,然后再将一个个小任务的结果进行汇总(join). 适用场 ...

  4. 类型转换辅助工具类TypeCaseHelper

    package org.sakaiproject.util; import java.math.BigDecimal; import java.sql.Date; import java.sql.Ti ...

  5. 多线程状态与优先级、线程同步与Monitor类、死锁

    一.线程状态 二.线程优先级 三.初步尝试多线程 class Program { static void Main(string[] args) { while (true) { MessagePri ...

  6. JUC——线程同步锁(锁处理机制简介)

    锁处理机制简介 juc的开发框架解决的核心问题是并发访问和数据安全操作问题,当进行并发访问的时候如果对于锁的控制不当,就会造成死锁这样的阻塞问题. 为了解决这样的缺陷,juc里面重新针对于锁的概念进行 ...

  7. 【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore

    前言 JUC中为了满足在并发编程中不同的需求,提供了几个工具类供我们使用,分别是CountDownLatch.CyclicBarrier和Semaphore,其原理都是使用了AQS来实现,下面分别进行 ...

  8. Java并发(十六):并发工具类——Exchanger

    Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法交换数 ...

  9. 线程同步之ManualResetEvent类的用法

    笔者的一台激光测厚设备的软件, 它有一个运动线程, 一个激光数据处理线程. 运动线程做的事就是由A点移动到B点, 然后再由B点移动回A点. 激光处理线程要做的事就是采集指定数量点的激光数据, 随着采集 ...

随机推荐

  1. 开发一个shopify插件

       开发一个shopify插件,shopify商城可以安装该插件:当用户在商城下单后,插件把订单数据按照指定格式传给disruptsports服务器:   https://help.shopify. ...

  2. mysql 索引分类以及用途分析

    MySQL索引分为普通索引.唯一性索引.全文索引.单列索引.多列索引等等.这里将为大家介绍着几种索引各自的用途. 一. MySQL: 索引以B树格式保存 Memory存储引擎可以选择Hash或BTre ...

  3. c++ thread 使用不当导致的崩溃问题

    看个例子 class CTimer{ public: // 析构函数 virtual ~CTimer(){ } // 开始 void start() { b_exit = false; i = ; t ...

  4. Kubernetes 初探

    一.容器: 1. 容器是运行一个或一组进程的方法,使得这些进程和主机上其他进程相隔离 2. 容器类似于虚拟机,但不同于虚拟机 容器                                    ...

  5. Caused by: org.apache.velocity.exception.MethodInvocationException: Invocation of method 'getUser' in class org.uncommons.reportng.ReportMetadata threw exception class java.net.UnknownHostException :

    Running TestSuite [TestNG] [WARN] Ignoring duplicate listener : org.uncommons.reportng.HTMLReporter ...

  6. openstack self-service 实例 连接外网数据表流程

    我的openstack的架构是最简单的controller-compute架构,在provider基础上创建self-service  self-service的实例上外网的流量走向 登陆实例,pin ...

  7. ubuntu下安装eclipse IDE for C/C++ developers

     序 linux的GUI和windos比起来实在逊色,虽然它的终端模式(命令行模式)非常强大.linux发行版ubuntu的GUI相对其他版本要华丽一些,所以最近由redhat转向ubuntu进行li ...

  8. oracle 子查询 where having from ,from子查询提高效率

    where 子查询主要功能是控制数据行的,返回结果一般都是单行单列.多行单列.单行多列数据 单行单列 SELECT * FROM emp WHERE hiredate=( SELECT MIN(hir ...

  9. 简单利用Clover四叶草安装U盘安装黑苹果

    配置是I5-7600K+技嘉Z270X-UD3+GTX 1050+简单利用Clover四叶草安装U盘安装黑苹果 <ignore_js_op><ignore_js_op> 成功黑 ...

  10. python3通过纯真IP数据库查询IP归属地信息

    在网上看到的别人写的python2的代码,修改成了python3. 把纯真IP数据库文件qqwry.dat放到czip.py同一目录下. #! /usr/bin/env python # -*- co ...