什么减慢了异步生产者的速度

时间:2017-06-10 12:17:32

标签: java multithreading asynchronous concurrency

我有一个java程序,其中包含一个发送消息的生产者和处理它们的消费者。下面是我的代码的简化版本,有两个测试来重现问题。

  • 类MyActor 是一个消费者线程。它只是循环读取来自并发队列的消息并对它们进行计数。

  • TestestMessagesToThread 是一个通过将200M消息发布到MyActor队列来同步发送200M消息的测试。它在我的机器上以每秒6M的速率工作。

  • testMessagesToThreadAsync 是一个以异步方式发送200M消息的测试。为了做到这一点,它创建了带有1个线程的ExecutorService,并且消息从该线程异步发布到MyActor队列。此测试每秒几乎不会达到100K消息,并且随着时间的推移会降低性能。

如何在使用ExecutorService时以 TestestMessagesToThread 的速率运行 TestestMessagesToThread ,或者至少了解为什么它不可能。

public class TestSingleThread {

    public static int WARM_UP_NUMBER = 1000000;
    public static int MSG_NUMBER = 200000000;
    private static ExecutorService _executor = Executors.newSingleThreadExecutor();

    public static class MyActor extends Thread {
        public Queue<Integer> _messageQueue = new ConcurrentLinkedQueue();
        private int _counter = 0;
        private long _time = System.currentTimeMillis();;

        public void run() {
            while (true){
                Integer msg = _messageQueue.poll();
                if (msg == null)
                    continue;

                _counter++;
                if (_counter == TestSingleThread.WARM_UP_NUMBER) {
                    System.out.println("Warm-up completed. Staring Measurement. Warm up time: " + (System.currentTimeMillis() - _time));
                    _time = System.currentTimeMillis();

                }

                if (_counter == TestSingleThread.MSG_NUMBER + TestSingleThread.WARM_UP_NUMBER) {
                    long endTime = System.currentTimeMillis();
                    long ms = endTime - _time;
                    System.out.println("Time for " + TestSingleActor.MSG_NUMBER+ " messages. " + ms);
                    System.out.println("msg/sec - " + (int) ((double) TestSingleActor.MSG_NUMBER / ms) * 1000);
                    _time = endTime;
                    break;
                }
            }
            System.out.println("Thread Run ends");
            return;
        }


        public void tell(Integer msg) {
            _messageQueue.add(msg);
        }

        public void tellAsync(Integer msg) {
            _executor.submit(() -> {
                _messageQueue.add(msg);
            });
        }
    }

    @Test
    public void testMessagesToThread() throws InterruptedException {
        MyActor actor = new MyActor();
        actor.start();
        IntStream.range(0, TestSingleActor.MSG_NUMBER + TestSingleActor.WARM_UP_NUMBER).sequential().forEach(record -> actor.tell(1));
        System.out.println("Complete Sending");
        actor.join();
        return;
    }

    @Test
    public void testMessagesToThreadAsync() throws InterruptedException {
        MyActor actor = new MyActor();
        actor.start();
        IntStream.range(0, TestSingleActor.MSG_NUMBER + TestSingleActor.WARM_UP_NUMBER).sequential().forEach(record -> actor.tellAsync(5));
        System.out.println("Complete Sending");
        actor.join();
    }
}

0 个答案:

没有答案