如何使用Exchanger在Java中的线程间共享对象?示例教程

124 阅读6分钟

大家好,如果你正在使用一个并发的Java应用程序,那么你可能听说过java.util.concurrent包中的Exchanger类。Java中的Exchanger是Java 1.5中引入的另一个并发或同步工具,与CountDownLatchCyclicBarrierSemaphores一样。顾名思义,Exchanger允许两个线程在汇合点或会合点相遇并交换数据。这意味着你可以使用Exchanger在线程之间共享对象,并进行线程间通信。java.util.Exchanger是一个参数类,它定义并持有要交换的对象的类型。它有一个叫做exchange()的重载方法,用来在线程之间交换对象。

这是一个阻塞的方法,这意味着调用exchange()方法的线程在交换点等待,直到另一个线程到达。一旦另一个线程到达,双方就会交换对象并从这个方法中返回。exchange方法的重载版本接受一个额外的TimeUnit对象,并等待直到超时。

顺便说一下,你也可以中断一个在交换点等待其他参与者的Thread。与CountDownLatch、CyclicBarrier或Semaphore不同,Exchanger 工具 只能同步两个线程,这使它成为解决经典的生产者-消费者问题的理想选择。

在这个Java并发性教程中,你将学习如何在Java中使用Exchanger,通过使用Exchanger实现生产者-消费者设计模式。Btw,我假设你已经熟悉了Java编程的语法和语义,如果你是一个完全的Java初学者,那么你可能会发现很难理解这个例子。

在这种情况下,我建议你先学习一门全面的Java课程,如Udemy上Tim Buchalaka的**The Complete Java Masterclass**。 这也是非常实惠的,你只需在Udemy的促销活动中花10美元就可以买到,这种情况时有发生。

线程间通信的Java交换器实例

Exchanger 类是一个相当简单的同步工具,易于理解和使用。在过去的几个并发教程中,我们已经用等待和通知解决了生产者-消费者的问题(见这里),还用BlockingQueue实现了生产者-消费者,现在是时候用Exchanger来实现同样的功能了。

在这个Java并发教程中,我们将创建一个生产者和一个消费者线程,它们将使用Exchanger实用类交换缓冲区。

一般来说,Exchanger是这样工作的:

1.你首先创建一个Exchange对象,比如 Exchanger<Deque> stringExchanger = new Exchanger<>(); 这定义了线程之间将交换什么类型的对象。在本例中,两个线程将交换Deque对象,包含长值。

2.当线程A准备好交换其缓冲区或对象时,它会调用Exchanger.exchange()方法。这是一个阻塞方法线程A将被阻塞,直到线程B来把它的对象传输给线程A,或者线程A被中断或超时。

3.当线程B准备好了,它也会调用exchange()方法。现在,线程A和线程B都交换对方的对象,并从交换方法中返回。

4.一旦交换完成,线程A就拥有线程B的对象,反之亦然。

同样,我想强调Java并发技能的重要性,并敦促每个Java开发人员花一些时间来掌握Java并发类。如果你同意我的观点,并且需要一个资源来提高你的Java并发技能,那么我强烈建议你去看一下经典的Java并发实践》一书和Udemy上的《Java中的多线程和并行计算课程,这两本书都是很好的资源。

在并发中使用交换器的Java程序

下面是我们完整的Java程序,演示如何使用Java并发API中的Exchanger实用类。你可以在你喜欢的IDE中复制粘贴这个程序,比如IntelliJIDEA或Eclipse,然后运行这个程序。

import
 
                    stack.
                        // Exchanger return other Thread's object
                        stack 
        //sleeping before starting consumer to give producer time to produce
        
        consumer.

交换器是如何工作的?它是如何传递对象的?

如果你看一下上面的例子,所有代码都在main方法里面。我们将Exchanger 实例设为final,因为我们要从匿名内类中访问它们,而且只有final局部变量才能从匿名内类中访问。

后来,我们创建了两个线程,生产者消费者。生产者检查队列,如果队列是空的,它就加入当前纳米时间的最后三位数字,并调用exchange()方法。

现在,在消费者线程到达交换点之前,我是说在它调用交换()方法之前,生产者线程将被阻塞。

一旦有消费者到达,双方就会交换对方的堆栈,并从exchange() 方法返回。此时,生产者有一个空的消费者堆栈,消费者有一个非空的生产者堆栈,我的意思是,他们有彼此的对象。

为了理解,哪个线程在交换哪个栈,我们在每个线程上打印交换前后的栈的内容。如果你看一下输出,那就不言自明了。

顺便说一下,和线程一样,你不能保证以相同的顺序获得输出。在第三个迭代中,你可以看到消费者有一个清空的堆栈,甚至在生产者线程得到安排并从交换方法中返回之前,就已经准备好交换空的堆栈。

以上就是关于如何在Java中使用交换器类的全部内容。Exchanger类是一个不错的、简单的同步工具,非常适合协调两个线程。 你可以使用Java中的Exchanger在两个线程之间轻松分享对象。Exchanger也可以用来实现一个生产者和一个消费者的生产者-消费者模式。如果你想了解更多关于Java并发类的信息,我建议你查看以下资源。

你可能会喜欢的其他Java并发性文章

  • Java开发者路线图(Roadmap)
  • 什么是Java并发中的happen-before?(答案)
  • 10个Java多线程和并发性最佳实践(文章)
  • Java中的前50个多线程和并发问题(问题)
  • 掌握Java并发性的5大书籍(书籍)
  • 适合初学者和中级开发人员的10个免费Java课程(课程)
  • 如何避免Java中的死锁?(答案)
  • 了解Java程序中的数据和代码流(答案)
  • 实践中的Java并发仍然有效吗(答案)
  • Java中CyclicBarrier和CountDownLatch的区别?(答案)
  • 在Java中工作之前是如何发生的? (答案)
  • 成为一个更好的Java开发者的10个技巧(提示)
  • 如何在Java中使用wait-notify进行线程间通信?(答案)
  • 深入学习Java多线程的5大课程(课程)

感谢你到目前为止阅读这篇文章。如果你喜欢这篇Java并发教程,那么请与你的朋友和同事分享它。如果您有任何问题或反馈,那么请留言。

P.S. - 如果你是Java世界的新手,想学习核心概念和并发性,但又想找一些免费课程开始学习,那么你也可以看看Udemy上的免费Java多线程课程。这也是学习Java并发性的一个很好的免费课程。