hreadPoolExecutor的getActiveCount

hreadPoolExecutor的getActiveCount

本文介绍了ThreadPoolExecutor的getActiveCount()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我调用getActiveCount()时,我有一个似乎在骗我的ThreadPoolExecutor。我没有做过很多多线程编程,所以也许我做错了。

I have a ThreadPoolExecutor that seems to be lying to me when I call getActiveCount(). I haven't done a lot of multithreaded programming however, so perhaps I'm doing something incorrectly.

这是我的TPE

@Override
public void afterPropertiesSet() throws Exception {

    BlockingQueue<Runnable> workQueue;
    int maxQueueLength = threadPoolConfiguration.getMaximumQueueLength();
    if (maxQueueLength == 0) {
        workQueue = new LinkedBlockingQueue<Runnable>();
    } else {
        workQueue = new LinkedBlockingQueue<Runnable>(maxQueueLength);
    }

    pool = new ThreadPoolExecutor(
                   threadPoolConfiguration.getCorePoolSize(),
                   threadPoolConfiguration.getMaximumPoolSize(),
                   threadPoolConfiguration.getKeepAliveTime(),
                   TimeUnit.valueOf(threadPoolConfiguration.getTimeUnit()),
                   workQueue,
                   // Default thread factory creates normal-priority,
                   // non-daemon threads.
                   Executors.defaultThreadFactory(),
                   // Run any rejected task directly in the calling thread.
                   // In this way no records will be lost due to rejection
                   // however, no records will be added to the workQueue
                   // while the calling thread is processing a Task, so set
                   // your queue-size appropriately.
                   //
                   // This also means MaxThreadCount+1 tasks may run
                   // concurrently. If you REALLY want a max of MaxThreadCount
                   // threads don't use this.
                   new ThreadPoolExecutor.CallerRunsPolicy());
}

在这个课程中,我还有一个DAO,我将其传递给我的Runnable( FooWorker ),如下所示:

In this class I also have a DAO that I pass into my Runnable (FooWorker), like so:

@Override
public void addTask(FooRecord record) {
    if (pool == null) {
        throw new FooException(ERROR_THREAD_POOL_CONFIGURATION_NOT_SET);
    }
    pool.execute(new FooWorker(context, calculator, dao, record));
}

FooWorker 运行记录(唯一的非单例)通过状态机通过计算器然后通过<$ c将转换发送到数据库$ c> dao ,如下所示:

FooWorker runs record (the only non-singleton) through a state machine via calculator then sends the transitions to the database via dao, like so:

public void run() {
    calculator.calculate(record);
    dao.save(record);
}

一旦我的主线程完成创建新任务我试着等待确保所有主题成功完成:

Once my main thread is done creating new tasks I try and wait to make sure all threads finished successfully:

while (pool.getActiveCount() > 0) {
    recordHandler.awaitTermination(terminationTimeout,
                                   terminationTimeoutUnit);
}

我从输出日志中看到的内容(由于以下内容可能不可靠) threading)是getActiveCount()太早返回零,而while()循环正在退出,而我的最后一个线程仍然是从计算器打印输出。

What I'm seeing from output logs (which are presumably unreliable due to the threading) is that getActiveCount() is returning zero too early, and the while() loop is exiting while my last threads are still printing output from calculator.

注意我也试过调用 pool.shutdown()然后使用 awaitTermination 但是下次我的工作运行时,游泳池仍然关闭。

Note I've also tried calling pool.shutdown() then using awaitTermination but then the next time my job runs the pool is still shut down.

当我发送时,我唯一的猜测是一个线程内的数据进入 dao (因为它是Spring在主线程中创建的单例...),java正在考虑该线程处于非活动状态(我假设)它正在处理/等待主线程。

My only guess is that inside a thread, when I send data into the dao (since it's a singleton created by Spring in the main thread...), java is considering the thread inactive since (I assume) it's processing in/waiting on the main thread.

直观地,仅基于我所看到的,这是我的猜测。但是......真的发生了什么事吗?有没有办法正确,而不在 run()的顶部放置手动递增变量,并在结束时递减以跟踪线程数?

Intuitively, based only on what I'm seeing, that's my guess. But... Is that really what's happening? Is there a way to "do it right" without putting a manual incremented variable at the top of run() and a decremented at the end to track the number of threads?

如果答案是不要传入dao,那么我不会为每个线程新DAO吗?我的过程已经是一个(美丽,高效)的野兽,但那真的很糟糕。

If the answer is "don't pass in the dao", then wouldn't I have to "new" a DAO for every thread? My process is already a (beautiful, efficient) beast, but that would really suck.

推荐答案

as ,这是一个近似值:你不应该根据这个做出任何重大的业务逻辑决策。

As the JavaDoc of getActiveCount states, it's an approximate value: you should not base any major business logic decisions on this.

如果你想等待要完成所有计划任务,那么您应该只使用

If you want to wait for all scheduled tasks to complete, then you should simply use

pool.shutdown();
pool.awaitTermination(terminationTimeout, terminationTimeoutUnit);

如果您需要等待特定的任务完成,您应该使用而不是 execute(),然后检查对象完成(使用如果您想要非阻塞或只需调用哪些块直到任务完成。)

If you need to wait for a specific task to finish, you should use submit() instead of execute() and then check the Future object for completion (either using isDone() if you want to do it non-blocking or by simply calling get() which blocks until the task is done).

这篇关于ThreadPoolExecutor的getActiveCount()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 07:10