Java 在服务内实现线程池

Java 在服务内实现线程池,java,android,multithreading,android-service,Java,Android,Multithreading,Android Service,我目前正在实现一个服务,当被请求时,它将在几个并行线程上执行一些工作 我的实现基于ThreadPoolExecutor类以及LinkedBlockingQueue 作为基本规则,一旦所有任务都完成并且队列中没有挂起的任务,我想停止该服务(尽管稍后可以再次启动该服务并遵循相同的逻辑) 我已经能够使用下面的代码达到预期的结果,但是我不确定这种方法是否正确 public class TestService extends Service { // Sets the initial thread

我目前正在实现一个
服务
,当被请求时,它将在几个并行线程上执行一些工作

我的实现基于
ThreadPoolExecutor
类以及
LinkedBlockingQueue

作为基本规则,一旦所有任务都完成并且队列中没有挂起的任务,我想停止该服务(尽管稍后可以再次启动该服务并遵循相同的逻辑)

我已经能够使用下面的代码达到预期的结果,但是我不确定这种方法是否正确

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();
    }
}
公共类TestService扩展服务{
//将初始线程池大小设置为3
私有静态最终int核心池大小=3;
//将最大线程池大小设置为3
私有静态最终整数最大池大小=3;
//设置空闲线程在终止前等待任务的时间量
私有静态final int KEEP_ALIVE_TIME=1;
//将时间单位设置为秒
专用静态最终时间单位KEEP_ALIVE_TIME_UNIT=TimeUnit.SECONDS;
//上载池的可运行程序队列
private final LinkedBlockingQueue uploadQueue=新建LinkedBlockingQueue();
//后台上载线程的托管池
私有最终ThreadPoolExecutor uploadThreadPool=新ThreadPoolExecutor(
核心池大小,最大池大小,保持活动时间,保持活动时间单位,
上载队列){
@凌驾
执行后受保护的无效(可运行的r、可丢弃的t){
super.afterExecute(r,t);
如果(getActiveCount()==1&&getQueue().size()==0){
//我们是最后一个可运行队列+队列为空,服务可以
//安全停止。
TestService.this.stopSelf();
}
}
};
@凌驾
公共IBinder onBind(意向){
返回null;
}
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId){
//执行一个新的Runnable
uploadThreadPool.execute(newtestrunnable());
/**
*表示如果Android必须关闭此服务(即内存不足),
*一旦情况改善,它不应重新启动。
*/
返回开始时间不粘;
}
@凌驾
公共空间{
uploadThreadPool.shutdownNow();
uploadQueue.clear();
super.ondestory();
}
}
所以我有一些事情我还不确定

  • 假设调用了
    onDestroy
    ,是否可以安全地假设我的实现将中断所有正在运行的线程,并安全地清除挂起的任务,而不会以某种方式中断
    ThreadPoolExecutor
    类实现?我询问的原因是队列与执行器关联,并且可能
    shutdownow
    是异步的,这取决于队列的状态。有更好的方法吗

  • 在onDestroy中实现此逻辑正确吗?根据我的经验,在某些情况下,服务被终止(即内存不足),并且不调用此回调。我是否也应该在其他地方执行类似的方法

  • 将队列和执行器类成员声明为静态会更好吗?--如@TheTwo
    “Excecutor所述,一旦调用“关机”
    ,则不能再次使用

  • ThreadPoolExecutor
    类需要一个
    BlockingQueue
    ,使用其他类型的
    BlockingQueue
    实现(即
    ArrayBlockingQueue
    )的优缺点是什么

  • 关于我当前检测队列何时为空的方式&没有更多挂起的任务(特别是在
    afterExecute
    callback中)——这是最好的方法吗?或者我可以得到队列为空且任务以另一种方式完成的指示吗

  • 谢谢你的帮助

  • 否。Shutdownow尝试中断当前正在执行的任务。无法保证它能够做到这一点
  • 是的。从文件中:

    一旦这两种情况都不成立,服务的onDestroy()就会 方法并有效终止服务。全部的 清理(停止线程、注销接收器)应完成 从onDestroy()返回时
  • 没有理由将这些成员声明为静态的<代码>静态成员与E类关联,而不是与任何对象关联,并且常见的用途是在不同(在您的情况下是服务)实例之间共享同一静态成员
  • 您应该仔细阅读有关
    BlockingQueue
    接口所有可能实现的文档,但我怀疑,对于正常情况下的使用,您是否会从性能角度看到差异

  • 我认为您正在尝试实现一个服务,它引入了许多问题,但没有解决任何问题。实际上,您将调用代码减少了一行—创建执行器—但却失去了对其进行精细控制的能力。调度许多任务没有任何好处,因为这已经由操作系统的线程调度器解决了。另外,一个恶意的调用方可以通过在(真)睡眠(100)时添加足够的
    来破坏其他几个程序循环

    关于你的问题:

  • 您无法确保所有线程都被正确中断,因为无法中断未正确监视中断标志的线程。A
    while(真)System.exit()
    中断代码>。从理论上讲,您可以停止线程,但由于某种原因,此功能被弃用,因为它可能使实际任务处于未完成/未完成状态(即使TCP连接半开)

  • 不,您没有正确地实现这一点。就这一次