1919import java .util .concurrent .Executors ;
2020import java .util .concurrent .ScheduledExecutorService ;
2121import java .util .concurrent .ScheduledFuture ;
22+ import java .util .concurrent .ThreadFactory ;
2223import java .util .concurrent .TimeUnit ;
2324import java .util .concurrent .locks .ReentrantLock ;
2425
@@ -40,7 +41,7 @@ public abstract class BackgroundService
4041 * Executor service
4142 */
4243 private ScheduledExecutorService executorService ;
43-
44+
4445 /**
4546 * Next iteration
4647 */
@@ -56,7 +57,7 @@ public abstract class BackgroundService
5657 * @throws Exception
5758 */
5859 protected abstract void startUp () throws Exception ;
59-
60+
6061 /**
6162 * Run one iteration of the background service
6263 * @throws Exception
@@ -67,7 +68,7 @@ public abstract class BackgroundService
6768 * @return The next schedule delay (between iterations) in milliseconds
6869 */
6970 protected abstract long getNextScheduleDelayMilliseconds ();
70-
71+
7172 /**
7273 * Shut down the background service
7374 * @throws Exception
@@ -78,24 +79,32 @@ public abstract class BackgroundService
7879 * Start the background service/thread
7980 */
8081 public void start () {
81-
82+
8283 lock .lock ();
83-
84+
8485 try {
85- executorService = Executors .newSingleThreadScheduledExecutor ();
86-
86+ executorService = Executors .newSingleThreadScheduledExecutor (new ThreadFactory () {
87+ @ Override
88+ public Thread newThread (Runnable r ) {
89+ Thread thread = new Thread (r );
90+ thread .setName ("StackifyLoggingBackgroundThread" );
91+ thread .setDaemon (true );
92+ return thread ;
93+ }
94+ });
95+
8796 try {
8897 startUp ();
8998 } catch (Throwable t ) {
9099 LOGGER .info ("Exception in service start up" , t );
91100 }
92-
101+
93102 currentFuture = executorService .schedule (new RunOneIterationAndReschedule (), 0 , TimeUnit .MILLISECONDS );
94103 } finally {
95104 lock .unlock ();
96105 }
97106 }
98-
107+
99108 /**
100109 * @return True if the background service is running, false otherwise
101110 */
@@ -105,26 +114,26 @@ public boolean isRunning() {
105114 return true ;
106115 }
107116 }
108-
117+
109118 return false ;
110119 }
111-
120+
112121 /**
113122 * Stops the background service/thread
114123 */
115124 public void stop () {
116-
125+
117126 lock .lock ();
118-
127+
119128 try {
120129 currentFuture .cancel (false );
121-
130+
122131 try {
123132 shutDown ();
124133 } catch (Throwable t ) {
125134 LOGGER .info ("Exception in service shut down" , t );
126135 }
127-
136+
128137 try {
129138 executorService .shutdown ();
130139 executorService .awaitTermination (5 , TimeUnit .SECONDS );
@@ -135,7 +144,7 @@ public void stop() {
135144 lock .unlock ();
136145 }
137146 }
138-
147+
139148 /**
140149 * RunOneIterationAndReschedule
141150 */
@@ -146,23 +155,23 @@ private class RunOneIterationAndReschedule implements Callable<Void> {
146155 */
147156 @ Override
148157 public Void call () throws Exception {
149-
158+
150159 // run one iteration
151-
160+
152161 lock .lock ();
153-
162+
154163 try {
155164 runOneIteration ();
156165 } catch (Throwable t ) {
157166 LOGGER .info ("Exception in iteration" , t );
158167 } finally {
159168 lock .unlock ();
160169 }
161-
170+
162171 // reschedule
163-
172+
164173 lock .lock ();
165-
174+
166175 try {
167176 if (!currentFuture .isCancelled ()) {
168177 long nextDelay = getNextScheduleDelayMilliseconds ();
@@ -173,7 +182,7 @@ public Void call() throws Exception {
173182 } finally {
174183 lock .unlock ();
175184 }
176-
185+
177186 // done
178187
179188 return null ;
0 commit comments