- 浏览: 467220 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
ty1972873004:
sunwang810812 写道我运行了这个例子,怎么结果是这 ...
Java并发编程: 使用Semaphore限制资源并发访问的线程数 -
lgh1992314:
simpleDean 写道请问,Logger.setLevel ...
Java内置Logger详解 -
sunwang810812:
我运行了这个例子,怎么结果是这样的:2号车泊车6号车泊车5号车 ...
Java并发编程: 使用Semaphore限制资源并发访问的线程数 -
jp260715007:
nanjiwubing123 写道参考你的用法,用如下方式实现 ...
面试题--三个线程循环打印ABC10次的几种解决方法 -
cb_0312:
SurnameDictionary文章我没看完,现在懂了
中文排序
本文介绍Exchanger工具类, 然后采用Exchanger给出一个两个线程交换数值的简单实例。
1. Exchanger介绍
/** * A synchronization point at which two threads can exchange objects. * Each thread presents some object on entry to the {@link #exchange * exchange} method, and receives the object presented by the other * thread on return. */
从上面的注释中可以看出:Exchanger提供了一个同步点,在这个同步点,两个线程可以交换数据。每个线程通过exchange()方法的入口提供数据给另外的线程,并接收其它线程提供的数据,并返回。
Exchanger通过Lock和Condition来完成功能,Exchanger的一个重要的public方法是exchange方法,用于线程的数据交换, 相关的类图以及详细的Exchanger类内容如下:
package java.util.concurrent; import java.util.concurrent.locks.*; /** * A synchronization point at which two threads can exchange objects. * Each thread presents some object on entry to the {@link #exchange * exchange} method, and receives the object presented by the other * thread on return. * * <p><b>Sample Usage:</b> * Here are the highlights of a class that uses an <tt>Exchanger</tt> to * swap buffers between threads so that the thread filling the * buffer gets a freshly * emptied one when it needs it, handing off the filled one to * the thread emptying the buffer. * <pre> * class FillAndEmpty { * Exchanger<DataBuffer> exchanger = new Exchanger(); * DataBuffer initialEmptyBuffer = ... a made-up type * DataBuffer initialFullBuffer = ... * * class FillingLoop implements Runnable { * public void run() { * DataBuffer currentBuffer = initialEmptyBuffer; * try { * while (currentBuffer != null) { * addToBuffer(currentBuffer); * if (currentBuffer.full()) * currentBuffer = exchanger.exchange(currentBuffer); * } * } catch (InterruptedException ex) { ... handle ... } * } * } * * class EmptyingLoop implements Runnable { * public void run() { * DataBuffer currentBuffer = initialFullBuffer; * try { * while (currentBuffer != null) { * takeFromBuffer(currentBuffer); * if (currentBuffer.empty()) * currentBuffer = exchanger.exchange(currentBuffer); * } * } catch (InterruptedException ex) { ... handle ...} * } * } * * void start() { * new Thread(new FillingLoop()).start(); * new Thread(new EmptyingLoop()).start(); * } * } * </pre> * * @since 1.5 * @author Doug Lea * @param <V> The type of objects that may be exchanged */ public class Exchanger<V> { private final ReentrantLock lock = new ReentrantLock(); private final Condition taken = lock.newCondition(); /** Holder for the item being exchanged */ private V item; /** * Arrival count transitions from 0 to 1 to 2 then back to 0 * during an exchange. */ private int arrivalCount; /** * Main exchange function, handling the different policy variants. */ private V doExchange(V x, boolean timed, long nanos) throws InterruptedException, TimeoutException { lock.lock(); try { V other; // If arrival count already at two, we must wait for // a previous pair to finish and reset the count; while (arrivalCount == 2) { if (!timed) taken.await(); else if (nanos > 0) nanos = taken.awaitNanos(nanos); else throw new TimeoutException(); } int count = ++arrivalCount; // If item is already waiting, replace it and signal other thread if (count == 2) { other = item; item = x; taken.signal(); return other; } // Otherwise, set item and wait for another thread to // replace it and signal us. item = x; InterruptedException interrupted = null; try { while (arrivalCount != 2) { if (!timed) taken.await(); else if (nanos > 0) nanos = taken.awaitNanos(nanos); else break; // timed out } } catch (InterruptedException ie) { interrupted = ie; } // Get and reset item and count after the wait. // (We need to do this even if wait was aborted.) other = item; item = null; count = arrivalCount; arrivalCount = 0; taken.signal(); // If the other thread replaced item, then we must // continue even if cancelled. if (count == 2) { if (interrupted != null) Thread.currentThread().interrupt(); return other; } // If no one is waiting for us, we can back out if (interrupted != null) throw interrupted; else // must be timeout throw new TimeoutException(); } finally { lock.unlock(); } } /** * Create a new Exchanger. **/ public Exchanger() { } /** * Waits for another thread to arrive at this exchange point (unless * it is {@link Thread#interrupt interrupted}), * and then transfers the given object to it, receiving its object * in return. * <p>If another thread is already waiting at the exchange point then * it is resumed for thread scheduling purposes and receives the object * passed in by the current thread. The current thread returns immediately, * receiving the object passed to the exchange by that other thread. * <p>If no other thread is already waiting at the exchange then the * current thread is disabled for thread scheduling purposes and lies * dormant until one of two things happens: * [list] * <li>Some other thread enters the exchange; or * <li>Some other thread {@link Thread#interrupt interrupts} the current * thread. * [/list] * <p>If the current thread: * [list] * <li>has its interrupted status set on entry to this method; or * <li>is {@link Thread#interrupt interrupted} while waiting * for the exchange, * [/list] * then {@link InterruptedException} is thrown and the current thread's * interrupted status is cleared. * * @param x the object to exchange * @return the object provided by the other thread. * @throws InterruptedException if current thread was interrupted * while waiting **/ public V exchange(V x) throws InterruptedException { try { return doExchange(x, false, 0); } catch (TimeoutException cannotHappen) { throw new Error(cannotHappen); } } /** * Waits for another thread to arrive at this exchange point (unless * it is {@link Thread#interrupt interrupted}, or the specified waiting * time elapses), * and then transfers the given object to it, receiving its object * in return. * * <p>If another thread is already waiting at the exchange point then * it is resumed for thread scheduling purposes and receives the object * passed in by the current thread. The current thread returns immediately, * receiving the object passed to the exchange by that other thread. * * <p>If no other thread is already waiting at the exchange then the * current thread is disabled for thread scheduling purposes and lies * dormant until one of three things happens: * [list] * <li>Some other thread enters the exchange; or * <li>Some other thread {@link Thread#interrupt interrupts} the current * thread; or * <li>The specified waiting time elapses. * [/list] * <p>If the current thread: * [list] * <li>has its interrupted status set on entry to this method; or * <li>is {@link Thread#interrupt interrupted} while waiting * for the exchange, * [/list] * then {@link InterruptedException} is thrown and the current thread's * interrupted status is cleared. * * <p>If the specified waiting time elapses then {@link TimeoutException} * is thrown. * If the time is * less than or equal to zero, the method will not wait at all. * * @param x the object to exchange * @param timeout the maximum time to wait * @param unit the time unit of the <tt>timeout</tt> argument. * @return the object provided by the other thread. * @throws InterruptedException if current thread was interrupted * while waiting * @throws TimeoutException if the specified waiting time elapses before * another thread enters the exchange. **/ public V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException { return doExchange(x, true, unit.toNanos(timeout)); } }
2. Exchanger工具类的使用案例
本文给出一个简单的例子,实现两个线程之间交换数据,用Exchanger来做非常简单。
package my.concurrent.exchanger; import java.util.concurrent.Exchanger; import java.util.concurrent.atomic.AtomicReference; public class ThreadA implements Runnable { private final Exchanger<Integer> exchanger; private final AtomicReference<Integer> last = new AtomicReference<Integer>( 5); public ThreadA(Exchanger<Integer> exchanger) { this.exchanger = exchanger; } public void run() { try { while (true) { last.set(exchanger.exchange(last.get())); System.out.println(" After calling exchange. Thread A has value: " + last.get()); Thread.sleep(2000); } } catch (InterruptedException e) { e.printStackTrace(); } } }
package my.concurrent.exchanger; import java.util.concurrent.Exchanger; import java.util.concurrent.atomic.AtomicReference; public class ThreadB implements Runnable { private Exchanger<Integer> exchanger; private final AtomicReference<Integer> last = new AtomicReference<Integer>( 10); public ThreadB(Exchanger<Integer> exchanger) { this.exchanger = exchanger; } public void run() { try { while (true) { last.set(exchanger.exchange(last.get())); System.out.println(" After calling exchange. Thread B has value: " + last.get()); Thread.sleep(2000); } } catch (InterruptedException e) { e.printStackTrace(); } } }
package my.concurrent.exchanger; import java.util.concurrent.Exchanger; public class ExchangerTest { public static void main(String[] args) { Exchanger<Integer> exchanger = new Exchanger<Integer>(); new Thread(new ThreadA(exchanger)).start(); new Thread(new ThreadB(exchanger)).start(); } }
运行一段时间之后的输出结果如下:
After calling exchange. Thread B has value: 5
After calling exchange. Thread A has value: 10
After calling exchange. Thread B has value: 10
After calling exchange. Thread A has value: 5
After calling exchange. Thread A has value: 10
After calling exchange. Thread B has value: 5
After calling exchange. Thread B has value: 10
After calling exchange. Thread A has value: 5
After calling exchange. Thread A has value: 10
After calling exchange. Thread B has value: 5
After calling exchange. Thread B has value: 10
After calling exchange. Thread A has value: 5
After calling exchange. Thread A has value: 10
After calling exchange. Thread B has value: 5
After calling exchange. Thread A has value: 5
After calling exchange. Thread B has value: 10
After calling exchange. Thread A has value: 10
After calling exchange. Thread B has value: 5
After calling exchange. Thread B has value: 10
After calling exchange. Thread A has value: 5
After calling exchange. Thread B has value: 5
After calling exchange. Thread A has value: 10
After calling exchange. Thread A has value: 5
After calling exchange. Thread B has value: 10
After calling exchange. Thread B has value: 5
After calling exchange. Thread A has value: 10
After calling exchange. Thread B has value: 10
After calling exchange. Thread A has value: 5
After calling exchange. Thread B has value: 5
After calling exchange. Thread A has value: 10
可以看出:两个线程的数据一直都在相互交换。
发表评论
-
工厂类中移除if/else语句
2016-07-10 19:52 908面向对象语言的一个强大的特性是多态,它可以用来在代码中移除 ... -
Java编程练手100题
2014-12-11 17:13 6733本文给出100道Java编程练手的程序。 列表如下: 面 ... -
数组复制的三种方法
2014-11-30 12:57 2221本文将给出三种实现数组复制的方法 (以复制整数数组为例)。 ... -
数组复制的三种方法
2014-11-30 12:54 0本文将给出三种实现数组复制的方法 (以复制整数数组为例)。 ... -
四种复制文件的方法
2014-11-29 13:21 1744尽管Java提供了一个类ava.io.File用于文件的操 ... -
判断一个字符串中的字符是否都只出现一次
2014-11-25 12:58 2733本篇博文将给大家带来几个判断一个字符串中的字符是否都只出现一 ... -
使用正则表达式判断一个数是否为素数
2014-11-23 13:35 2174正则表达式能够用于判断一个数是否为素数,这个以前完全没有想过 ... -
几个可以用英文单词表达的正则表达式
2014-11-21 13:12 3758本文,我们将来看一下几个可以用英文单词表达的正则表达式。这些 ... -
(广度优先搜索)打印所有可能的括号组合
2014-11-20 11:58 1960问题:给定一个正整n,作为括号的对数,输出所有括号可能 ... -
随机产生由特殊字符,大小写字母以及数字组成的字符串,且每种字符都至少出现一次
2014-11-19 14:48 3984题目:随机产生字符串,字符串中的字符只能由特殊字符 (! ... -
找出1到n缺失的一个数
2014-11-18 12:57 3184题目:Problem description: You h ... -
EnumSet的几个例子
2014-11-14 16:24 8758EnumSet 是一个与枚举类型一起使用的专用 Set 实现 ... -
给定两个有序数组和一个指定的sum值,从两个数组中各找一个数使得这两个数的和与指定的sum值相差最小
2014-11-12 11:24 3334题目:给定两个有序数组和一个指定的sum值,从两个数组 ... -
Java面试编程题练手
2014-11-04 22:49 6706面试编程 写一个程序,去除有序数组中的重复数字 编 ... -
Collections用法整理
2014-10-22 20:55 9851Collections (java.util.Collect ... -
The Code Sample 代码实例 个人博客开通
2014-09-04 18:48 1423个人博客小站开通 http://thecodesample. ... -
Collections.emptyXXX方法
2014-06-08 13:37 2148从JDK 1.5开始, Collections集合工具类中预先 ... -
这代码怎么就打印出"hello world"了呢?
2014-06-08 00:37 7400for (long l = 4946144450195624L ... -
最短时间过桥
2014-04-21 22:03 4158本文用代码实现最短时间过桥,并且打印如下两个例子的最小过桥时间 ... -
将数组分割成差值最小的子集
2014-04-20 22:34 2906本文使用位掩码实现一个功能 ==》将数组分割成差值最小的子集 ...
相关推荐
《Java并发编程:设计原则与模式》是一本深入探讨Java多线程编程的书籍,它涵盖了并发编程中的关键概念、原则和模式。在Java中,并发处理是优化应用程序性能、提高资源利用率的重要手段,尤其在现代多核处理器的环境...
根据给定文件的信息“JAVA并发编程实践”以及其描述为“Java并发学习资料”,我们可以从中提炼出关于Java并发编程的一些核心知识点。Java并发编程是Java高级特性之一,它允许开发者编写能够同时执行多个任务的程序,...
线程安全的数据结构,如ConcurrentHashMap、ConcurrentLinkedQueue等,是Java并发编程的重要组成部分。它们内部实现了线程安全的更新策略,能够在高并发环境下保证数据一致性。 异常处理在多线程编程中同样重要。...
Java并发编程是Java语言中最为复杂且重要的部分之一,它涉及了多线程编程、内存模型、同步机制等多个领域。为了深入理解Java并发编程,有必要了解其核心技术点和相关实现原理,以下将详细介绍文件中提及的关键知识点...
6. **线程池**:Executor框架是Java并发编程的重要组成部分,讲解ThreadPoolExecutor的使用,包括线程池的参数配置、工作队列的选择以及线程池的生命周期管理。 7. **死锁与活锁**:分析可能导致线程死锁的原因,...
- 可视化阻塞数据结构:如`Exchanger`,用于线程间数据交换。 5. **第五章:线程池** - `Executor`框架:线程池的创建、管理和关闭。 - `ThreadPoolExecutor`的参数配置:核心线程数、最大线程数、工作队列等。 ...
- **Exchanger**:允许两个线程交换对象的工具类。 ### Java并发编程实战案例 #### 1. 生产者消费者模式 生产者消费者模式是一种经典的多线程设计模式,用于解决多线程之间如何共享数据的问题。在Java中可以通过`...
Java多线程编程中的Exchanger是一个非常有用的工具类,它位于`java.util.concurrent`包下,主要用于线程间的数据交换。Exchanger的核心功能是让两个线程在一个同步点相遇,进行数据交换。当一个线程调用`exchange`...
《JAVA并发编程实践》是一本深入探讨Java多线程与并发控制的权威书籍,中文版本的出现使得更多国内开发者能够无障碍地学习这方面的知识。这本书不仅涵盖了理论基础,还提供了丰富的实战示例,包括源码,使读者能够...
根据提供的文件信息,“Java并发编程实战”这本书主要聚焦于Java并发编程的核心概念和技术。下面将对并发编程的一些关键知识点进行详细解析。 ### 并发与并行 在深入讨论Java并发编程之前,我们首先需要理解并发...
Java并发编程技术是Java开发中的重要领域,它涉及到如何在多线程环境下高效地执行程序。并发编程可以充分利用多核处理器资源,提高系统的响应速度和处理能力。以下是一些核心的知识点: 1. **并行程序**:并行程序...
在Java并发编程中,Exchanger是一个非常有用的工具类,它允许两个线程间进行数据交换。这个类在处理需要同步的交互式任务时特别有用,比如在多阶段处理或者需要线程间协作的情况。Exchanger的工作原理就像一个中介,...
Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...
Java并发工具类是Java并发编程中的重要组成部分,其中包括了多种实用的工具,如CountDownLatch、Semaphore和Exchanger,这些工具类极大地简化了多线程环境下的同步和协调问题。 1. **CountDownLatch**: ...
- **Exchanger**:用于线程间的数据交换。 #### 五、代理模式简介 除了线程的基础知识外,给定的内容还提到了**代理模式**,这是一种设计模式,用于在不改变原有接口的前提下,为对象添加新的责任。代理模式通常...
`java.util.concurrent`包是Java标准库中专门用于并发编程的模块,它包含了各种线程安全的数据结构、同步机制和执行模型。这个包的引入极大地简化了并发编程的复杂性,提供了一套高效且易用的并发工具。 **3.2 ...