本文介绍了实现服务中的一个线程池的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在实施服务,当要求将在多个并行线程执行一些工作。

I'm currently working on implementing a Service that when requested will perform some work on several parallel threads.

我的实现是基于的ThreadPoolExecutor 类连同的LinkedBlockingQueue

My implementation is based on the ThreadPoolExecutor class along with a LinkedBlockingQueue.

作为一个基本规则,一旦所有的任务都完成,在队列中没有未决的任务,我想停止服务(尽管该服务可以在以后再次启动,并按照相同的逻辑)。

As a ground rule, once all tasks are finished and the are no pending tasks in the queue, I would like to stop the service (though the service can later on be started again and follow the same logic).

我已经能够使用下面的code,以达到理想的结果,但我不知道这种做法是正确的。

I have been able to reach the desired outcome using the code below, yet I'm not sure if this approach is correct.

public class TestService extends Service {
    // Sets the initial threadpool size to 3
    private static final int CORE_POOL_SIZE = 3;

    // Sets the maximum threadpool size to 3
    private static final int MAXIMUM_POOL_SIZE = 3;

    // Sets the amount of time an idle thread will wait for a task before terminating
    private static final int KEEP_ALIVE_TIME = 1;

    // Sets the Time Unit to seconds
    private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;

    // A queue of Runnables for the uploading pool
    private final LinkedBlockingQueue<Runnable> uploadQueue = new LinkedBlockingQueue<Runnable>();

    // A managed pool of background upload threads
    private final ThreadPoolExecutor uploadThreadPool = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT,
            uploadQueue) {

        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);

            if (getActiveCount() == 1 && getQueue().size() == 0) {
                // we're the last Runnable around + queue is empty, service can be
                // safely stopped.
                TestService.this.stopSelf();
            }
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // execute a new Runnable
        uploadThreadPool.execute(new TestRunnable());

        /**
         * Indicating that if Android has to kill off this service (i.e. low memory),
         * it should not restart it once conditions improve.
         */
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        uploadThreadPool.shutdownNow();
        uploadQueue.clear();

        super.onDestroy();
    }
}

所以,我有一些事情我还没有肯定。

So I've got a few things I'm not yet sure about.

  1. 假设的onDestroy 被称为,它是安全的假设,我的执行将中断所有正在运行的线程,并安全地清除挂起任务,而无需用某种方式中断的ThreadPoolExecutor 类实现?我问的原因是因为队列与执行程序有关,也许执行shutdownNow 是异步并根据队列的状态。是否有这样做的更好的办法?

  1. Assuming onDestroy was called, is it safe to assume that my implementation will interrupt ALL running threads and will safely clear the pending tasks without somehow interrupting with the ThreadPoolExecutor class implementation? the reason I'm asking is because the queue is associated with the executor, and perhaps shutdownNow is async and depending on the state of the queue. Is there a better way of doing this?

我是正确实施内部的onDestroy 这样的逻辑?从我的经验,也有一些情况下,该服务被杀死(即低内存),这回叫不叫。我应该执行在其他地方类似的做法呢?

Am I correct implementing this logic inside onDestroy? from my experience there are some cases where the service is killed (i.e. low memory) and this callback is not called. Should I perform a similar approach in other places as well?

它会更好声明我的队列和放大器;遗嘱执行人类成员静态 - ?正如由@TheTwo Excecutor不能再使用一次关闭被称为

-- As stated by @TheTwo "Excecutor cannot be re-used once shutdown is called".

的ThreadPoolExecutor 类需要一个的BlockingQueue ,有什么利弊/使用其它类型的缺点的BlockingQueue 实现(即 ArrayBlockingQueue

ThreadPoolExecutor class expects a BlockingQueue, what are the pros/cons of using other types of BlockingQueue implementations (i.e. ArrayBlockingQueue)?

对于我现在发现当队列为空和放的方式;没有更多的尚未完成的任务(特别是在 afterExecute 回调) - 这是这样做的最好方法是什么?或者,我可以得到的指示队列为空和任务以另一种方式完成?

Regarding the way I currently detect when the queue is empty & there are no more pending tasks (specifically inside afterExecute callback) -- Is this the best way of doing this? Or can I get an indication that the queue is empty and tasks are finished in another way?

鸭preciate任何帮助!

Appreciate any help!

推荐答案

我想你是想实现一个服务,它引入了很多问题,但解决了没有。有效您可以通过一条线减少调用code - 创建的执行者 - 但带走进行精细控制的能力。中没有调度的许多任务的任何增益,因为这已经解决了由OS'线程调度。此外恶意调用者可以只需添加足够的破坏其它几个项目,而(真)睡眠(100); 循环。

I think you are trying to implement a service, which introduces many problems, but solves none. Effectively you reduce the calling code by one line - the creation of the Executor - but take away the ability to fine-control it. There isn't any gain in scheduling many tasks, as this is already solved by the OS' thread scheduler. In addition a malicious caller can break several other programs by just adding enough while(true) sleep(100); loops.

在你的问题:

  1. 您不能确保所有线程都正常中断过,因为没有办法打断一个线程是不正确的观看中断标志。 A ,而(真); 无法除非中断System.exit()的。理论上你就可以停止一个线程,但是这个功能是pcated的一个原因去$ P $,因为它可以把实际工作中的不完整/未完成的状态(即让TCP-连接的半开)。

  1. You cannot make sure that all threads are properly interrupted ever, because there is no way to interrupt a thread that is not properly watching the interrupt flag. A while(true) ; cannot be interrupted except by System.exit(). You could theoretically stop a thread, but this feature is deprecated for a reason, because it can leave the actual task in an incomplete/unfinished state (i.E. leaving TCP-connections half-open).

没有,你是不是正确地实现这一点。这一次的任务留给诠释他排队只会消失在虚空中,然后一个Excecutor不能再使用一次关机时调用。所以,你至少需要创建的服务启动一个新的Excecutor实例,你真的应该弄清楚如何处理余下的任务。

No, you are not correctly implementing that. For once tasks left int he queue would simply vanish in the void, and then an Excecutor cannot be re-used once shutdown is called. So you at least need to create a new Excecutor instance on service start, and you really should figure out what to do with the remaining tasks.

由于2号。

的优点/列表类型的利弊取决于你的用例。越来越多的时候/缩小,但以较低的成本时,索引的特定元素(的indexOf),而链表是左右相反的ArrayList具有较高的性价比。由于您的队列总是添加到尾,不关心其他任何元素,但第一次,它的增长/收缩频繁,链表是最好的选择。

The pros/cons of list types depend on your use-case. An ArrayList has a higher cost when growing/shrinking but a lower cost when indexing a specific element (indexOf), while a linked-list is about the opposite. Since your queue always adds to the tail, doesn't care about any other element but the first, and it is growing/shrinking frequently, a linked-list is the best choice.

您不应该停止任务这样可言,因为执行与线程的顺序是不确定的。在最坏的情况下你的调用程序每次直到服务执行完毕,这将导致服务不断启动&安培中断;停止对无特殊原因,而浪费了大量的处理时间白白。为什么你甚至想停止该服务?如果它没有任何关系,它不会做任何事情,但使用的内存的几个字节。

You should not stop the task this way at all, because the order of execution with threads is undefined. In worst case your calling program is interrupted each time till the service is done executing, which will cause the service to constantly start & stop for no particular reason, while wasting a lot of processing time for nothing. Why would you even want to stop the service? If it has nothing to do, it won't do anything but to use a few bytes of memory.

这篇关于实现服务中的一个线程池的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-16 02:20