【问题标题】:Sending objects back and forth between threads in java?在java中的线程之间来回发送对象?
【发布时间】:2011-12-02 16:22:24
【问题描述】:

我有多个客户端处理程序线程,这些线程需要将接收到的对象传递给服务器队列,服务器队列会将另一种类型的对象传递回发送线程。服务器队列启动并在服务器启动时继续运行。我不确定客户端处理程序线程使用哪种线程机制通知对象被发回。我不打算使用套接字或写入文件。

【问题讨论】:

  • 在线程之间共享对象引用很容易,但您还需要在线程之间发出信号吗?例如。让一个指示另一个“请处理这个对象”,然后“好的,处理完成,请处理返回值”。

标签: java multithreading thread-safety


【解决方案1】:

如果您想进行实际的消息传递,请查看SynchronusQueue。每个线程都会引用队列,并一直等到一个线程通过队列传递引用。

这将是线程安全的并满足您的要求。

如果您只是想让线程读取和写入共享变量,您可以使用 normalocity 的建议,尽管它的线程安全性取决于您如何访问它(通过同步或易失性)

【讨论】:

  • +1 - 这是我对共享对象集合的引用的一个很好的扩展,并且肯定会完成这项工作。
【解决方案2】:

就在 Java 中使对象可访问而言,多线程和单线程之间没有区别。您只需遵循范围规则(公共、私有、受保护),仅此而已。多个线程都在同一个进程中运行,因此无需了解任何特殊的仅线程范围规则。

例如,定义一个传递对象的方法,并使该方法可从其他线程访问。您要传递的对象只需要可从其他线程的范围内访问即可。

就线程安全而言,you can synchronize your writes,并且在大多数情况下,这将解决问题。你的代码越复杂,线程安全就会变得有点麻烦,但我认为这会让你开始。

处理对象和生成结果对象的一种方法是使用一个共享数组或 LinkedList,它充当对象队列,包含要处理的对象以及该处理的结果对象。如果没有更多关于您到底想要做什么的细节,很难更详细地介绍,但是线程之间对对象的大多数共享访问归结为线程间方法调用或对象的一些共享集合/队列。

【讨论】:

  • shared array 您可能知道这一点,但是由于阅读时并不清楚,因此对其他人提出警告:易失性数组不等于易失性数组元素,因此您基本上需要那里的不安全代码-更好使用高级数据结构。
【解决方案3】:

除非您绝对确定一次始终只有一个对象,否则请使用某种队列。

如果您确定一次始终只有一个对象,请使用某种队列。 :-)

【讨论】:

    【解决方案4】:
    • 使用 java.util.concurrent.* 中的并发队列。

    为什么?几乎可以保证提供比任何手卷更好的一般性能。

    建议:使用绑定队列,您将免费获得背压。

    注意:队列的深度决定了您的一般延迟特性:较浅的队列将具有较低的延迟,但会降低带宽。

    • 使用 Future 语义

    为什么? Futures 提供了一种经过验证的标准方法来获取异步结果。

    建议:创建一个简单的 Request 类并公开一个方法#getFutureResponse()。该方法的实现可以使用多种信令策略,如Lock、flag(使用Atomic/CAS)等。

    注意:在 Future 中使用超时语义将允许您将服务器行为链接到您的服务器 SLA,例如#getFutureResponse(sla_timeout_ms)。

    【讨论】:

      【解决方案5】:

      如果您想更深入地研究线程(或进程或系统)之间的通信,请阅读本书提示:Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects

      【讨论】:

        【解决方案6】:

        只需使用简单的dependency injection

        MyFirstThread extends Thread{
         public void setData(Object o){...}
        }
        MySecondThread extends Thread{
           MyFirstThread callback;
           MySecondThread(MyFirstThread callback){this.callback=callback)
        }
        MyFirstThread t1 = new MyFirstThread();
        MySecondThread t2 = new MySecondThread(t1);    
        t1.start();
        t2.start();
        

        您现在可以在第二个线程中执行callback.setData(...)

        我认为这是最安全的方式。其他解决方案包括使用volatile 或某种共享对象,我认为这太过分了。

        您可能还想使用BlockingQueue 并将它们都传递给每个线程。如果您计划拥有多个线程,那么它可能是一个更好的解决方案。

        【讨论】:

        • 为什么要命名变量回调? otherThread 或其他东西不会更有意义吗? (毕竟不是函数)
        • 是的,这也是个好主意。我只是称它为callback,因为我想表明这是thread1 调用的东西。但实际上这是一个简单的解决方案,它表明如果您可以传递线程,那么您可以做任何事情。您还可以“同步”setter/getter。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多