【问题标题】:Execute Runnable lambda with more than on threads using ScheduledExecutorService使用 ScheduledExecutorService 执行具有多个线程的 Runnable lambda
【发布时间】:2016-07-14 08:58:42
【问题描述】:

我有一个方法 start() 可以创建一个带有 lambda 的 Runnable。在该方法中,我启动了一个使用该 Runnable 的 ScheduledExecutorService。我认为如果只使用 1 个线程来执行任务,我不会有问题,但是如果我启动多个线程并在内部传递相同的 Runnable 会发生什么。示例代码如下:

public class MessageProcessor { 
    private final ServiceA serviceA;
    private final ServiceB serviceB;
    private final ScheduledExecutorService executor;

    public MessageProcessor() {
        this.executor = Executors.newScheduledThreadPool(1);
        this.serviceA = new ServiceA();
        this.serviceB = new ServiceB();
    }

    public void start() {

        Runnable messageProcessingTask = () -> {
            try {
                List<Message> messages = serviceA.receiveMessages();
                messages.forEach(m -> {
                    boolean success = serviceB.doSomething(m);
                    if (success) serviceB.deleteMessage(m);
                    else LOG.error("failed to process the message bla bla...");
                });
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        };

        executor.scheduleWithFixedDelay(messageProcessingTask, 0, 1, TimeUnit.SECONDS);
    }

    public void stop() {
        executor.shutdown();
    }
}

如果将代码更改为使用 2 个线程会发生什么:

    public class MessageProcessor { 

        .....

        public MessageProcessor() {
            this.executor = Executors.newScheduledThreadPool(2);
            this.serviceA = new ServiceA();
            this.serviceB = new ServiceB();
        }

        public void start() {

            Runnable messageProcessingTask = () -> {
                try {
                    List<Message> messages = serviceA.receiveMessages();
                    messages.forEach(m -> {
                        boolean success = serviceB.doSomething(m);
                        if (success) serviceB.deleteMessage(m);
                        else LOG.error("failed to process the message bla bla...");
                    });
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            };

            executor.scheduleWithFixedDelay(messageProcessingTask, 0, 1, TimeUnit.SECONDS);
            executor.scheduleWithFixedDelay(messageProcessingTask, 0, 1, TimeUnit.SECONDS);
        }

        ....
    }
  1. 这种方法是不好的做法吗?
  2. 如果此代码导致错误,我该如何生成它们?
  3. 如果这是一种不好的方法,最佳做法是什么?

提前致谢。

【问题讨论】:

  • serviceA.receiveMessages() 的两次调用会返回相同(或重叠)的消息列表还是不同的消息列表?
  • serviceA.receiveMessages() 从消息队列中返回一批 10 条消息,每次都有不同的消息。列表不会相互重叠
  • 那应该问题不大。
  • 谢谢,看来会没事的。 :)

标签: java multithreading lambda executorservice scheduledexecutorservice


【解决方案1】:

如果将代码更改为使用 2 个线程会发生什么

嗯,这两个任务将以固定的延迟同时执行。他们都将尝试从服务 A 接收消息,使用服务 B 做某事并删除他们收到的每条消息,然后在一秒钟后再次执行。

是不是你想要的,serviceA 和 serviceB 是否能够处理并发调用都是未知的,所以由你来决定。

【讨论】:

  • 感谢您的回答。当我增加线程数时,它似乎有效,我无法证明它的科学思想。我会监控行为,看看情况如何。
猜你喜欢
  • 2011-10-14
  • 1970-01-01
  • 2011-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 1970-01-01
相关资源
最近更新 更多