相同的Runnable类两次传递给同时运行两个/多个线程的ExecutorService [英] Same Runnable class being passed twice to the ExecutorService running two/multiple threads at the same time

查看:81
本文介绍了相同的Runnable类两次传递给同时运行两个/多个线程的ExecutorService的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个可运行类,并且我想通过集中式类(称为启动器类,其中包含所有可运行对象的列表)与执行程序服务一起运行它们.

I have multiple runnable classes and I want to run them with executor service through a centralized class (call it Launcher class which contains list of all runnables).

我编写了一个 Launcher 类,该类使用 applicationContext.getBean()实例化所有bean.每个可运行类还为其定义一个 pool size (为此可运行类产生的线程数).

I wrote a Launcher class which takes all the beans to instantiate using applicationContext.getBean(). Each runnable class also defines a pool size for it (number of threads to spawn for this runnable).

public class DaemonsLauncher {

    @Autowired
    private ApplicationContext appContext;

    private List<Daemon> daemons = new ArrayList<Daemon>();

    private ScheduledThreadPoolExecutor executor;

    private void initThreadPool() throws Exception {
        //daemonNames coming at run time from somewhere.
        List<String> daemonList = Arrays.asList(daemonNames.split(Constant.COMMA));
        //Pool size will now be summation of all the pool sizes.
        int poolSize = 0;
        for (String dName : daemonList) {
            Daemon daemon = appContext.getBean(dName, Daemon.class);
            poolSize += daemon.getPoolSize();
            daemons.add(daemon);
        }
        executor = new ScheduledThreadPoolExecutor(poolSize);
    }

    public void launchDaemons() throws Exception {
        for (Daemon daemon : daemons) {
            for (int currentThreadCount = 1; currentThreadCount <= daemon.getPoolSize(); currentThreadCount++) {
                executor.scheduleWithFixedDelay(daemon, 0, XYZ, ABC);
            }
        }
    }
}

在执行此操作的过程中,我将所有可运行对象添加到 List< Daemon> (其中,Daemon是抽象的可运行类,由其他守护程序扩展).

In the process of doing it, I add all runnables to a List<Daemon> (where Daemon is a abstract runnable class which is extended by other daemons).

public abstract class Daemon implements Runnable {

    protected int poolSize = 1;

    public int getPoolSize() {
        return poolSize;
    }

    @Override
    public void run() {
        //Calls run methods of individual runnables here.
    }

}

如您所见,我在执行时多次添加每个可运行类的相同实例(取决于poolSize).

As you can see, I add same instance of each runnable class multiple times(depending on poolSize) while executing.

executor ScheduledThreadPoolExecutor .

此刻,调用 R 的run方法时,我两次都找到了可运行类的相同实例,因为它们只被 appContext.getBean()占用了一次(通过打印hasCode和toString检查).

The moment, run method of R is called, I find same instance of runnable class both the times since they were taken only once by appContext.getBean() (checked by printing hasCode and toString).

但是这些可运行类的多个实例同时运行.

But these multiple instances of runnable class run at the same time.

这种情况可能是什么问题?这些多个线程在相同的可运行状态下运行会导致问题还是会正常?

What might be the issue with this sort of case? Are these multiple threads running for same runnable will cause issues or it will go fine?

作为替代方案,根据poolSize,即使在此循环之前,我也可以获取Runnable类的多个实例,并且仅根据列表中存在的所有"Runnable"条目循环一次.

As an alternative, depending on poolSize, I can get multiple instances of the Runnable class even before this loop and loop only once depending on all the 'Runnable' entries present in the List.

  1. 所有bean本质上都是原型(尽管不会出现在图片中,因为我仅一次调用过appContext.getBean).
  2. 一个示例可运行类.

public class R extends Daemon {
    @Override
    public void runIndividualDaemon() {
        //Called by run of Daemon class.
        logger.info("Running Daemon." + this.hashCode() + " " + this.toString());
    }

    @Override
    protected void init() throws Exception {
        this.poolSize = 5;
    }
}

推荐答案

如果您多次执行一项任务,那是因为您多次添加了该任务.

If you have a task being performed multiple times, it is because you added it multiple times.

我建议您在添加任务时登录以确认这一点.

I suggest you log when you add tasks to confirm this.

但是同一线程正在执行两个线程的任务怎么会发生?

But how can it happen that same thread is performing task of two threads?

一个线程不能一次执行两项任务,但是可以重复使用同一线程来执行一项任务.

A thread cannot perform two tasks at once, but it can perform one task after another, re-using the same thread.

是我有两个'Runnable'类的实例"吗?如果那个bean是单例的,那不是这种情况吗?

Is it that "I have two instances of 'Runnable' class" which would not have been the case if that bean was singleton?

在这种情况下,我不认为添加两个相同的任务或两次添加相同的任务会带来很大的不同.

I don't believe add two tasks which are the same or adding the same task twice will make much difference in this case.

这篇关于相同的Runnable类两次传递给同时运行两个/多个线程的ExecutorService的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆