1
+ package fr.free.nrw.commons.concurrency
2
+
3
+ import java.util.concurrent.Callable
4
+ import java.util.concurrent.Executor
5
+ import java.util.concurrent.ScheduledFuture
6
+ import java.util.concurrent.ScheduledThreadPoolExecutor
7
+ import java.util.concurrent.ThreadFactory
8
+ import java.util.concurrent.TimeUnit
9
+
10
+
11
+ /* *
12
+ * This class is a thread pool which provides some additional features:
13
+ * - it sets the thread priority to a value lower than foreground priority by default, or you can
14
+ * supply your own priority
15
+ * - it gives you a way to handle exceptions thrown in the thread pool
16
+ */
17
+ class ThreadPoolService private constructor(builder : Builder ) : Executor {
18
+ private val backgroundPool: ScheduledThreadPoolExecutor = ExceptionAwareThreadPoolExecutor (
19
+ builder.poolSize,
20
+ object : ThreadFactory {
21
+ private var count = 0
22
+ override fun newThread (r : Runnable ): Thread {
23
+ count++
24
+ val t = Thread (r, " ${builder.name} -$count " )
25
+ // If the priority is specified out of range, we set the thread priority to
26
+ // Thread.MIN_PRIORITY
27
+ // It's done to prevent IllegalArgumentException and to prevent setting of
28
+ // improper high priority for a less priority task
29
+ t.priority =
30
+ if (
31
+ builder.priority > Thread .MAX_PRIORITY
32
+ ||
33
+ builder.priority < Thread .MIN_PRIORITY
34
+ ) {
35
+ Thread .MIN_PRIORITY
36
+ } else {
37
+ builder.priority
38
+ }
39
+ return t
40
+ }
41
+ },
42
+ builder.exceptionHandler
43
+ )
44
+
45
+ fun <V > schedule (callable : Callable <V >, time : Long , timeUnit : TimeUnit ): ScheduledFuture <V > {
46
+ return backgroundPool.schedule(callable, time, timeUnit)
47
+ }
48
+
49
+ fun schedule (runnable : Runnable ): ScheduledFuture <* > {
50
+ return schedule(runnable, 0 , TimeUnit .SECONDS )
51
+ }
52
+
53
+ fun schedule (runnable : Runnable , time : Long , timeUnit : TimeUnit ): ScheduledFuture <* > {
54
+ return backgroundPool.schedule(runnable, time, timeUnit)
55
+ }
56
+
57
+ fun scheduleAtFixedRate (
58
+ task : Runnable ,
59
+ initialDelay : Long ,
60
+ period : Long ,
61
+ timeUnit : TimeUnit
62
+ ): ScheduledFuture <* > {
63
+ return backgroundPool.scheduleWithFixedDelay(task, initialDelay, period, timeUnit)
64
+ }
65
+
66
+ fun executor (): ScheduledThreadPoolExecutor {
67
+ return backgroundPool
68
+ }
69
+
70
+ fun shutdown () {
71
+ backgroundPool.shutdown()
72
+ }
73
+
74
+ override fun execute (command : Runnable ) {
75
+ backgroundPool.execute(command)
76
+ }
77
+
78
+ /* *
79
+ * Builder class for [ThreadPoolService]
80
+ */
81
+ class Builder (val name : String ) {
82
+ var poolSize: Int = 1
83
+ var priority: Int = Thread .MIN_PRIORITY
84
+ var exceptionHandler: ExceptionHandler ? = null
85
+
86
+ /* *
87
+ * @param poolSize the number of threads to keep in the pool
88
+ * @throws IllegalArgumentException if size of pool <= 0
89
+ */
90
+ fun setPoolSize (poolSize : Int ): Builder {
91
+ if (poolSize <= 0 ) {
92
+ throw IllegalArgumentException (" Pool size must be greater than 0" )
93
+ }
94
+ this .poolSize = poolSize
95
+ return this
96
+ }
97
+
98
+ /* *
99
+ * @param priority Priority of the threads in the service. You can supply a constant from
100
+ * [java.lang.Thread] or
101
+ * specify your own priority in the range 1(MIN_PRIORITY)
102
+ * to 10(MAX_PRIORITY)
103
+ * By default, the priority is set to [java.lang.Thread.MIN_PRIORITY]
104
+ */
105
+ fun setPriority (priority : Int ): Builder {
106
+ this .priority = priority
107
+ return this
108
+ }
109
+
110
+ /* *
111
+ * @param handler The handler to use to handle exceptions in the service
112
+ */
113
+ fun setExceptionHandler (handler : ExceptionHandler ): Builder {
114
+ exceptionHandler = handler
115
+ return this
116
+ }
117
+
118
+ fun build (): ThreadPoolService {
119
+ return ThreadPoolService (this )
120
+ }
121
+ }
122
+ }
0 commit comments