Mercurial Hosting > nabble
comparison src/nabble/model/Executors.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7ecd1a4ef557 |
---|---|
1 package nabble.model; | |
2 | |
3 import java.util.Date; | |
4 import java.util.Random; | |
5 import java.util.concurrent.TimeUnit; | |
6 import org.slf4j.Logger; | |
7 import org.slf4j.LoggerFactory; | |
8 import fschmidt.db.DbDatabase; | |
9 import fschmidt.util.executor.RunnableWrapper; | |
10 import fschmidt.util.executor.ThreadPool; | |
11 import fschmidt.util.executor.ScheduledThreadPool; | |
12 import fschmidt.util.executor.ThreadTimer; | |
13 import fschmidt.util.java.DateUtils; | |
14 | |
15 | |
16 public final class Executors { | |
17 private Executors() {} // never | |
18 | |
19 private static final Logger logger = LoggerFactory.getLogger(Executors.class); | |
20 | |
21 public static final ThreadTimer threadTimer = new ThreadTimer(); | |
22 | |
23 private static final RunnableWrapper dbCleanup = new RunnableWrapper() { | |
24 @Override public Runnable wrap(final Runnable command) { | |
25 return new Runnable(){public void run(){ | |
26 try { | |
27 command.run(); | |
28 } finally { | |
29 fschmidt.db.pool.Pool.threadReset(); | |
30 } | |
31 }}; | |
32 } | |
33 }; | |
34 | |
35 private static final ScheduledThreadPool backgroundExecutor = new ScheduledThreadPool(1); | |
36 static { | |
37 backgroundExecutor.addRunnableWrapper(dbCleanup); | |
38 backgroundExecutor.addRunnableWrapper(threadTimer); | |
39 backgroundExecutor.addRunnableWrapper(new TimedExecuteWrapper()); | |
40 } | |
41 public static final ThreadPool foregroundExecutor = new ThreadPool(Init.get("poolSize",100)); | |
42 static { | |
43 foregroundExecutor.addRunnableWrapper(dbCleanup); | |
44 foregroundExecutor.addRunnableWrapper(threadTimer); | |
45 } | |
46 private static Random rnd = new Random(); | |
47 | |
48 private static final long timeLimit = Init.get("execTimeLimitSeconds", 60L); | |
49 private static volatile boolean isShuttingDown = false; | |
50 private static long start = System.currentTimeMillis(); | |
51 | |
52 static void shutdown() { | |
53 isShuttingDown = true; | |
54 backgroundExecutor.shutdown(); | |
55 foregroundExecutor.shutdown(); | |
56 try { | |
57 while( !backgroundExecutor.awaitTermination(1,TimeUnit.SECONDS) ) { | |
58 logger.error("backgroundExecutor failed to shutdown"); | |
59 for( Thread thread : backgroundExecutor.getThreads() ) { | |
60 if( thread.isAlive() ) { | |
61 Throwable t = new Throwable(thread.toString()); | |
62 t.setStackTrace(thread.getStackTrace()); | |
63 logger.error("backgroundExecutor thread",t); | |
64 } | |
65 } | |
66 } | |
67 /* why does this matter? | |
68 while( !foregroundExecutor.awaitTermination(1,TimeUnit.SECONDS) ) { | |
69 logger.error("foregroundExecutor failed to shutdown"); | |
70 for( Thread thread : foregroundExecutor.getThreads() ) { | |
71 if( thread.isAlive() ) { | |
72 Throwable t = new Throwable(thread.toString()); | |
73 t.setStackTrace(thread.getStackTrace()); | |
74 logger.error("foregroundExecutor thread",t); | |
75 } | |
76 } | |
77 } | |
78 */ | |
79 } catch(InterruptedException e) { | |
80 logger.error("",e); | |
81 } | |
82 } | |
83 | |
84 public static boolean isShuttingDown() { | |
85 long time = (System.currentTimeMillis() - start)/1000; | |
86 if( time > timeLimit ) | |
87 logger.error("exec took too long, " + time + " seconds",new Exception()); | |
88 start = System.currentTimeMillis(); | |
89 return isShuttingDown; | |
90 } | |
91 | |
92 private static final class TimedExecuteWrapper implements RunnableWrapper { | |
93 private ThreadLocal<Exception> trace = new ThreadLocal<Exception>() { | |
94 protected Exception initialValue() { | |
95 return new Exception("exec created"); | |
96 } | |
97 }; | |
98 | |
99 @Override public Runnable wrap(final Runnable command) { | |
100 return new Runnable(){public void run(){ | |
101 Thread.currentThread().setName("background-thread"); | |
102 trace.get(); | |
103 start = System.currentTimeMillis(); | |
104 try { | |
105 command.run(); | |
106 } finally { | |
107 long time = (System.currentTimeMillis() - start)/1000; | |
108 if( time > timeLimit ) | |
109 logger.error("exec took too long, " + time + " seconds",trace); | |
110 } | |
111 }}; | |
112 } | |
113 } | |
114 | |
115 public static void executeNow(Runnable command) { | |
116 foregroundExecutor.execute(command); | |
117 } | |
118 | |
119 | |
120 | |
121 public static void executeSometime(Runnable command) { | |
122 schedule(command,0,TimeUnit.SECONDS); | |
123 } | |
124 | |
125 public static void schedule(Runnable command,long delay,TimeUnit unit) { | |
126 backgroundExecutor.schedule(command,delay,unit); | |
127 } | |
128 | |
129 public static void scheduleWithFixedDelay(final Runnable command,long initialDelay,final long delay,final TimeUnit unit) { | |
130 Runnable repeatedCommand = new Runnable(){public void run(){ | |
131 command.run(); | |
132 schedule(this,delay,unit); | |
133 }}; | |
134 schedule(repeatedCommand,initialDelay,unit); | |
135 } | |
136 | |
137 public static void runDaily(Runnable task) { | |
138 scheduleWithFixedDelay(task, rnd.nextInt(60*60*24), 60*60*24, TimeUnit.SECONDS); | |
139 } | |
140 | |
141 private static final long MILLIS_PER_DAY = 1000L*60L*60L*24L; | |
142 | |
143 public static void runDaily(final Runnable task, int hour, int minute) { | |
144 final long millisAfterMidnight = ((long) hour * 60 + minute) * 60 * 1000; | |
145 Date now = new Date(); | |
146 long time = now.getTime() - DateUtils.roundToDay(now).getTime(); | |
147 long sleep = time < millisAfterMidnight | |
148 ? millisAfterMidnight - time | |
149 : MILLIS_PER_DAY - (time - millisAfterMidnight) | |
150 ; | |
151 scheduleWithFixedDelay(task, sleep/(1000L*60), 60*24, TimeUnit.MINUTES); | |
152 } | |
153 | |
154 public static void executeAfterCommit(DbDatabase db,final Runnable command) { | |
155 db.runAfterCommit(new Runnable(){public void run(){ | |
156 executeNow(command); | |
157 }}); | |
158 } | |
159 | |
160 } |