1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.pump.concurrent;
18 
19 import androidx.annotation.AnyThread;
20 import androidx.annotation.NonNull;
21 import androidx.annotation.Nullable;
22 
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.concurrent.BlockingQueue;
27 import java.util.concurrent.RejectedExecutionHandler;
28 import java.util.concurrent.ThreadFactory;
29 import java.util.concurrent.ThreadPoolExecutor;
30 import java.util.concurrent.TimeUnit;
31 
32 @AnyThread
33 public class UniqueExecutor extends ThreadPoolExecutor {
34     private final Collection<Runnable> mRunning = Collections.synchronizedSet(new HashSet<>());
35 
UniqueExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NonNull TimeUnit unit, @NonNull BlockingQueue<Runnable> workQueue)36     public UniqueExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
37             @NonNull TimeUnit unit, @NonNull BlockingQueue<Runnable> workQueue) {
38         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
39     }
40 
UniqueExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NonNull TimeUnit unit, @NonNull BlockingQueue<Runnable> workQueue, @NonNull ThreadFactory threadFactory)41     public UniqueExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
42             @NonNull TimeUnit unit, @NonNull BlockingQueue<Runnable> workQueue,
43             @NonNull ThreadFactory threadFactory) {
44         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
45     }
46 
UniqueExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NonNull TimeUnit unit, @NonNull BlockingQueue<Runnable> workQueue, @NonNull RejectedExecutionHandler handler)47     public UniqueExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
48             @NonNull TimeUnit unit, @NonNull BlockingQueue<Runnable> workQueue,
49             @NonNull RejectedExecutionHandler handler) {
50         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
51     }
52 
UniqueExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, @NonNull TimeUnit unit, @NonNull BlockingQueue<Runnable> workQueue, @NonNull ThreadFactory threadFactory, @NonNull RejectedExecutionHandler handler)53     public UniqueExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
54             @NonNull TimeUnit unit, @NonNull BlockingQueue<Runnable> workQueue,
55             @NonNull ThreadFactory threadFactory, @NonNull RejectedExecutionHandler handler) {
56         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory,
57                 handler);
58     }
59 
60     @Override
execute(@onNull Runnable command)61     public void execute(@NonNull Runnable command) {
62         if (!mRunning.add(command)) {
63             return;
64         }
65         super.execute(command);
66     }
67 
68     @Override
afterExecute(@onNull Runnable r, @Nullable Throwable t)69     protected void afterExecute(@NonNull Runnable r, @Nullable Throwable t) {
70         super.afterExecute(r, t);
71         mRunning.remove(r);
72     }
73 }
74