@@ -11,74 +11,12 @@ public class EVMLiSAExecutor {
1111 private static int CORES = (Runtime .getRuntime ().availableProcessors () > 1 )
1212 ? Runtime .getRuntime ().availableProcessors () - 1
1313 : 1 ;
14- private static ExecutorService _executor = Executors . newFixedThreadPool ( CORES );
14+ private static final ConcurrentMap < Class <?>, ExecutorService > ownerExecutors = new ConcurrentHashMap <>( );
1515
1616 private static long tasksInQueue = 0 ;
17- @ SuppressWarnings ("unused" )
1817 private static long tasksExecuted = 0 ;
1918 private static long tasksTimedOut = 0 ;
2019
21- /**
22- * Submits a task for execution in the thread pool.
23- *
24- * @param task the task to be executed
25- *
26- * @return a Future representing the pending result of the task
27- */
28- public static Future <?> submit (Runnable task ) {
29- return _executor .submit (new EVMLiSAExecutorTask (task ));
30- }
31-
32- /**
33- * Submits a list of tasks for execution in the thread pool.
34- *
35- * @param tasks the list of tasks to be executed
36- *
37- * @return a list of Future objects representing the pending results of the
38- * tasks
39- */
40- public static List <Future <?>> submitAll (List <Runnable > tasks ) {
41- List <Future <?>> futures = new ArrayList <>();
42-
43- for (Runnable task : tasks )
44- futures .add (submit (new EVMLiSAExecutorTask (task )));
45-
46- return futures ;
47- }
48-
49- /**
50- * Executes a main task asynchronously and schedules additional tasks upon
51- * its completion.
52- *
53- * @param mainTask the main task to execute
54- * @param secondaryTasks additional tasks to execute after the main task
55- *
56- * @return a CompletableFuture that completes when all tasks are finished
57- */
58- public static CompletableFuture <Void > runAsync (Runnable mainTask , Runnable ... secondaryTasks ) {
59- return runAsync (mainTask , Set .of (secondaryTasks ));
60- }
61-
62- /**
63- * Executes a main task asynchronously and schedules additional tasks upon
64- * its completion.
65- *
66- * @param mainTask the main task to execute
67- * @param secondaryTasks additional tasks to execute after the main task
68- *
69- * @return a CompletableFuture that completes when all tasks are finished
70- */
71- public static CompletableFuture <Void > runAsync (Runnable mainTask , Set <Runnable > secondaryTasks ) {
72- return CompletableFuture .runAsync (new EVMLiSAExecutorTask (mainTask ), _executor )
73- .thenCompose (ignored -> {
74- List <CompletableFuture <Void >> checkerFutures = new ArrayList <>();
75- for (Runnable secondaryTask : secondaryTasks )
76- checkerFutures
77- .add (CompletableFuture .runAsync (new EVMLiSAExecutorTask (secondaryTask ), _executor ));
78- return CompletableFuture .allOf (checkerFutures .toArray (new CompletableFuture [0 ]));
79- });
80- }
81-
8220 /**
8321 * Waits for the completion of all provided CompletableFutures.
8422 *
@@ -124,7 +62,6 @@ public static void awaitCompletionFutures(List<Future<?>> futures) {
12462 future .get ();
12563 } catch (ExecutionException e ) {
12664 System .err .println (JSONManager .throwNewError ("Error during task execution: " + e .getMessage ()));
127- e .printStackTrace ();
12865 System .exit (1 );
12966 } catch (InterruptedException ie ) {
13067 System .err .println (JSONManager .throwNewError ("Interrupted during task execution: " + ie .getMessage ()));
@@ -159,25 +96,108 @@ public static void awaitCompletionFutures(List<Future<?>> futures, long timeout,
15996 }
16097
16198 /**
162- * Shuts down the executor service, preventing new tasks from being
163- * submitted.
99+ * Creates (if absent) and returns an ExecutorService associated with the
100+ * given owner class. The created executor will have {@code threads} worker
101+ * threads. If an executor is already present for the owner, it is returned
102+ * unchanged.
103+ *
104+ * @param owner the class that will own the executor
105+ * @param threads number of threads for the executor (min 1)
106+ *
107+ * @return the ExecutorService associated with the owner
108+ */
109+ public static ExecutorService createExecutorFor (Class <?> owner , int threads ) {
110+ int t = Math .max (1 , threads );
111+ return ownerExecutors .computeIfAbsent (owner , k -> Executors .newFixedThreadPool (t ));
112+ }
113+
114+ /**
115+ * Returns the ExecutorService associated with the owner class, creating a
116+ * default single-threaded executor if none exists.
117+ *
118+ * @param owner the class that will own the executor
119+ *
120+ * @return the ExecutorService associated with the owner
121+ */
122+ public static ExecutorService getExecutorFor (Class <?> owner ) {
123+ return ownerExecutors .computeIfAbsent (owner , k -> Executors .newFixedThreadPool (CORES ));
124+ }
125+
126+ /**
127+ * Submits a task to the executor associated with the given owner class. If
128+ * no executor exists for the owner, a default one is created.
129+ *
130+ * @param owner the class owning the executor
131+ * @param task the runnable task to submit
132+ *
133+ * @return a Future representing pending completion of the task
134+ */
135+ public static Future <?> submit (Class <?> owner , Runnable task ) {
136+ ExecutorService ex = getExecutorFor (owner );
137+ return ex .submit (new EVMLiSAExecutorTask (task ));
138+ }
139+
140+ /**
141+ * Shuts down the executor associated with the given owner class. This
142+ * removes the executor from the internal map and calls shutdown on it. If
143+ * no executor is present, this is a no-op.
144+ *
145+ * @param owner the class whose executor should be shutdown
146+ */
147+ public static void shutdown (Class <?> owner ) {
148+ ExecutorService ex = ownerExecutors .remove (owner );
149+ if (ex != null )
150+ ex .shutdown ();
151+ }
152+
153+ /**
154+ * Shuts down all owner-bound executors.
155+ */
156+ public static void shutdownAllOwners () {
157+ for (Map .Entry <Class <?>, ExecutorService > e : ownerExecutors .entrySet ()) {
158+ executorShutdownQuiet (e .getValue ());
159+ }
160+ ownerExecutors .clear ();
161+ }
162+
163+ /**
164+ * Attempts to shut down the provided executor quietly, ignoring any
165+ * exceptions. This is a private helper used when shutting down multiple
166+ * executors.
167+ *
168+ * @param ex the executor service to shut down
164169 */
165- public static void shutdown () {
166- _executor .shutdown ();
170+ private static void executorShutdownQuiet (ExecutorService ex ) {
171+ try {
172+ ex .shutdown ();
173+ } catch (Exception ignored ) {
174+ }
167175 }
168176
177+ /**
178+ * Updates the number of cores available for per-owner executors. If the
179+ * provided value differs from the current configuration, all owner-bound
180+ * executors are shutdown and the internal core count is updated.
181+ *
182+ * @param cores desired number of cores (will be clamped to a minimum of 1
183+ * and at most the number of available processors - 1)
184+ */
169185 public static void setCoresAvailable (int cores ) {
170186 if (cores > Runtime .getRuntime ().availableProcessors ())
171187 cores = Runtime .getRuntime ().availableProcessors () - 1 ;
172188
173189 if (CORES == cores )
174190 return ;
175191
176- shutdown ();
192+ shutdownAllOwners ();
177193 CORES = Math .max (cores , 1 );
178- _executor = Executors .newFixedThreadPool (CORES );
179194 }
180195
196+ /**
197+ * Gets the current number of cores configured for owner executors.
198+ *
199+ * @return the configured core count
200+ */
181201 public static int getCoresAvailable () {
182202 return CORES ;
183203 }
0 commit comments