【问题标题】:inter thread communication in javajava中的线程间通信
【发布时间】:2011-01-11 08:21:00
【问题描述】:

相互依赖的线程如何在 Java 中进行通信?

例如,我正在构建一个带有线程的网络爬虫,这些线程需要来自其他线程的数据。

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    这取决于沟通的性质。

    • 是双工的(即 A 与 B 对话,B 与 A 对话)?
    • 是数据通信还是完成通信?

    等等。

    线程间通信最简单和最可取的形式就是等待其他线程完成。使用Future 最容易做到这一点:

    ExecutorService exec = Executors.newFixedThreadPool(50);
    final Future f = exec.submit(task1);
    exec.submit(new Runnable() {
        @Override
        public void run() {
            f.get();
            // do stuff
        }
    });
    

    在第一个任务完成之前,第二个任务不会执行。

    Java 5+ 有许多 并发实用程序来处理这类事情。这可能意味着使用LinkedBlockingQueues、CountDownLatch 或许多其他的。

    对于并发性的深入检查,Java Concurrency in Practice 是必读的。

    【讨论】:

    • 线程不是双向的,一个线程等待另一个线程的结果,反之亦然。诚然,我对 ExecutorService 和 Future 的使用有点害怕,因为我以前从未听说过它们。是否有另一种不使用 Future 和 ExecutorService 的线程间通信方法?
    • 没有必要被ExecutorServiceFuture 吓倒。它们相当简单,学习时间应该不到 2 小时。使用Futures 比标准队列类更容易,并且比使用wait()notify() 滚动您自己的队列类容易得多。
    • @cletus, -1 用于从 fixed 线程池的任务中调用 Future.get()。那里的危险应该是显而易见的。
    • @finnw:当然有危险,但如果没有交流的要求或更好的描述,你不可能提出没有危险的方法。
    • 这种特殊的危险可以通过使用缓存线程池来解决。
    【解决方案2】:

    看看java.util.Observer/java.util.Observable。 它们正是您正在寻找的。

    【讨论】:

    【解决方案3】:

    您可以使用 2 个 ExecutorServices,向服务 A 提交一个 Callable 实现,该实现知道服务 B 的后续操作。当 Callable 完成工作后,它会向服务 B 提交一个新任务,该任务对结果进行额外处理。

    如果您需要在两个服务中处理完所有项目后执行额外的工作,您可以使用 CountDownLatch 或其他一些障碍。

    ExecutorService api 非常简单,在大多数情况下,您可能会使用 .newFixedThreadPool(int threads) 之类的东西并向其提交 Runnables/Callables。

    【讨论】:

      【解决方案4】:

      以下是线程间通信的示例:

      public class Main {
          public static void main(String[] args) {
              Chat m = new Chat();
              new T1(m);
              new T2(m);
          }
      }
      
      class Chat {
          boolean flag = false;
      
          public synchronized void FromSam(String msg) {
              if (flag) {
                  try {
                      wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
              System.out.println(msg);
              flag = true;
              notify();
          }
      
          public synchronized void FromJam(String msg) {
              if (!flag) {
                  try {
                      wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
      
              System.out.println(msg);
              flag = false;
              notify();
          }
      }
      
      class T1 implements Runnable {
          Chat m;
          String[] s1 = { "Hello Jam", "How are you ?", "I am also doing fine!" };
      
          public T1(Chat m1) {
              this.m = m1;
              new Thread(this, "Sam").start();
          }
      
          public void run() {
              for (int i = 0; i < s1.length; i++) {
                  m.FromSam(s1[i]);
              }
          }
      }
      
      class T2 implements Runnable {
          Chat m;
          String[] s2 = { "HI Sam", "I am good,And U ?", "ha haa" };
      
          public T2(Chat m2) {
              this.m = m2;
              new Thread(this, "Jam").start();
          }
      
          public void run() {
              for (int i = 0; i < s2.length; i++) {
                  m.FromJam(s2[i]);
              }
          }
      }
      

      【讨论】:

      猜你喜欢
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 2013-05-18
      相关资源
      最近更新 更多