1 package com.atlassian.plugin.osgi.spring;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.springframework.core.task.AsyncTaskExecutor;
6
7 import javax.annotation.Nonnull;
8 import java.util.concurrent.Callable;
9 import java.util.concurrent.ExecutorService;
10 import java.util.concurrent.Executors;
11 import java.util.concurrent.Future;
12 import java.util.concurrent.ThreadFactory;
13 import java.util.concurrent.TimeUnit;
14 import java.util.concurrent.atomic.AtomicInteger;
15
16
17
18
19
20
21
22 public class ThreadPoolAsyncTaskExecutor implements AsyncTaskExecutor {
23 private static final Logger log = LoggerFactory.getLogger(ThreadPoolAsyncTaskExecutor.class);
24
25 private final ExecutorService executor = Executors.newCachedThreadPool(new NamedThreadFactory());
26
27
28
29
30
31
32
33 @Override
34 public void execute(@Nonnull Runnable task, long startTimeout) {
35
36 executor.execute(task);
37 }
38
39 @Nonnull
40 @Override
41 public Future<?> submit(@Nonnull Runnable task) {
42 return executor.submit(task);
43 }
44
45 @Nonnull
46 @Override
47 public <T> Future<T> submit(@Nonnull Callable<T> task) {
48 return executor.submit(task);
49 }
50
51
52
53
54
55
56 @Override
57 public void execute(@Nonnull Runnable task) {
58 this.execute(task, -1);
59 }
60
61
62
63
64
65 public void shutdown() {
66 log.debug("Attempting to shutdown ExecutorService");
67
68 executor.shutdown();
69 try {
70 if (executor.awaitTermination(5, TimeUnit.SECONDS)) {
71 log.debug("ExecutorService has shutdown gracefully");
72 } else {
73
74
75 log.warn("ExecutorService did not shutdown within the timeout; forcing shutdown");
76
77 executor.shutdownNow();
78 if (executor.awaitTermination(5, TimeUnit.SECONDS)) {
79
80 log.debug("ExecutorService has been forced to shutdown");
81 } else {
82
83
84
85 log.warn("ExecutorService did not shutdown; it will be abandoned");
86 }
87 }
88 } catch (InterruptedException e) {
89 log.warn("Interrupted while waiting for the executor service to shutdown; some worker threads may " +
90 "still be running");
91 Thread.currentThread().interrupt();
92 }
93 }
94
95
96
97
98 private static class NamedThreadFactory implements ThreadFactory {
99 private final AtomicInteger counter = new AtomicInteger();
100
101 @Override
102 public Thread newThread(@Nonnull Runnable r) {
103 Thread thread = new Thread(r);
104 thread.setDaemon(false);
105 thread.setName("ThreadPoolAsyncTaskExecutor::Thread " + counter.incrementAndGet());
106 return thread;
107 }
108 }
109 }