从两个单独的线程并行访问队列

时间:2014-10-09 11:51:50

标签: java multithreading queue

所以我的目标是测量 Streaming Engine 的性能。它基本上是一个我可以发送数据包的库。衡量这一点的想法是生成数据,将其放入队列,让 Streaming Engine 抓取数据并进行处理。

我想到这样实现它:数据生成器在一个线程中运行,并在无限循环中生成数据包,最后有一个Thread.sleep(X)。在进行测试时,我们的想法是最小化tis Thread.sleep(X)以查看它是否会对 Streaming Engine的性能产生影响。 数据生成器将创建的包写入队列,即ConcurrentLinkedQueue,同时也是一个单例。

在另一个线程中,我实例化 Streaming Engine ,它通过执行queue.remove()不断地从队列中删除包。这是在一个没有任何睡眠的endlees循环中完成的,因为它应该尽可能快地完成。

在第一次尝试实现这一点时,我遇到了一个问题。似乎数据生成器无法将软件包放入队列中。这样做太慢了。我怀疑 Streaming Engine 线程的无限循环占用了所有资源,因此减慢了其他所有资源。

我很高兴如何处理这个问题或其他设计模式,这可以优雅地解决这个问题。

要求是:基本上并行运行的2个线程。一个是将数据放入队列。另一个是从队列中读取/删除。我想定期测量队列的大小,以便知道从队列中读取/删除的引擎是否足够快以处理生成的包。

1 个答案:

答案 0 :(得分:1)

你可以使用BlockingQueue,例如ArrayBlockingQueue,你可以将它们初始化为一定的大小,因此排队的项目数量永远不会超过一定的数量,如下例所示:

// create queue, max size 100
final ArrayBlockingQueue<String> strings = new ArrayBlockingQueue<>(100);
final String stop = "STOP";

// start producing
Runnable producer = new Runnable() {
  @Override
  public void run() {
    try {
      for(int i = 0; i < 1000; i++) {
        strings.put(Integer.toHexString(i));
      }
      strings.put(stop);
    } catch(InterruptedException ignore) {
    }
  }
};

Thread producerThread = new Thread(producer);
producerThread.start();

// start monitoring
Runnable monitor = new Runnable() {
  @Override
  public void run() {
    try {
      while (true){
        System.out.println("Queue size: " + strings.size());
        Thread.sleep(5);
      }
    } catch(InterruptedException ignore) {
    }
  }
};
Thread monitorThread = new Thread(monitor);
monitorThread.start();

// start consuming
Runnable consumer = new Runnable() {
  @Override
  public void run() {
    // infinite look, will interrupt thread when complete
    try {
      while(true) {
        String value = strings.take();
        if(value.equals(stop)){
          return;
        }
        System.out.println(value);
      }
    } catch(InterruptedException ignore) {
    }
  }
};

Thread consumerThread = new Thread(consumer);
consumerThread.start();

// wait for producer to finish
producerThread.join();
consumerThread.join();

// interrupt consumer and monitor
monitorThread.interrupt();

您还可以使用第三个线程监视队列的大小,以便了解哪个线程超过了另一个线程。

此外,您可以使用定时put方法和定时或不定时的商品提供方法,这样可以让您更好地控制如果队列满或空的话该怎么做。在上面的示例中,执行将停止,直到有下一个元素的空间或队列中没有其他元素为止。