Scenario problem: Use the thread pool ExecutorService, and want to set the execution timeout time of each child thread. Use () to listen for the timeout. When a child thread is blocked, some queue tasks are cancelled before they are executed.
Method 1: Use () to listen for timeout cancellation
This method may seem to solve the problem, but when the task cannot be processed, execution will be missed.
For example, in the following example, it will actually only execute one child thread.
package ; import ; import ; import .*; public class Test { private static final DateTimeFormatter formatter = ("yyyy-MM-dd HH:mm:ss"); private static final ExecutorService threadPool = (1); public static void main(String[] args) throws Exception { for (int i = 0; i < 10; i++) { Future<?> future = (new Runnable() { @Override public void run() { try { (().format(formatter)); (5000); } catch (InterruptedException e) { // (); } } }); new Thread(new Runnable() { @Override public void run() { try { (3, ); } catch (InterruptedException e) { (); } catch (ExecutionException e) { (); } catch (TimeoutException e) {//Timeout exception (true); // Cancel the task after timeout } } }).start(); } } }
Method 2: Send interrupt signal after timeout within the child thread
package ; import ; import ; import .*; public class Test { private static final DateTimeFormatter formatter = ("yyyy-MM-dd HH:mm:ss"); private static final ExecutorService threadPool = (1); private static final ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(1);//The listening timeout, this number must be the same as the number of thread pools public static void main(String[] args) throws Exception { for (int i = 0; i < 10; i++) { // int delay = 3; int delay = i + 1; (new Runnable() { @Override public void run() { ScheduledFuture<?> schedule = null; try { Thread thread = (); // Start a timer, if the task is executed for more than 3 seconds, the current thread will be interrupted schedule = (() -> { (); // Interrupt the currently executing task }, delay, ); (().format(formatter)); (5000); // FileOutputStream fos = new FileOutputStream("d:/" + k); // for (int j = 0; j < 1000000; j++) { // ("123".getBytes()); // } // (); } catch (InterruptedException e) { // (); } finally { if (schedule != null) { //Cancel the task (true); } } } }); } } }
There is actually still a problem here. If you change (5000); to annotated io blocking, you still have to wait until the thread execution is finished before canceling the thread execution.
Therefore, simply using future cannot realize the logic of this scenario.
The reason why the number of timeoutExecutors and the number of thread pools should be consistent is as follows.
package ; import ; import ; import ; import ; public class ScheduledExecutorServiceExample { private static final ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(2); public static void main(String[] args) throws InterruptedException { // Call schedule method twice scheduleTask("Task 1"); scheduleTask("Task 2"); scheduleTask("Task 3"); } private static void scheduleTask(String taskName) { (() -> { (taskName + " started at: " + ()); try { // Simulate task execution (2000); // Assume that each task is executed for 2 seconds } catch (InterruptedException e) { ().interrupt(); } }, 3, ); } }
Method 3: Define the lock to implement it
package ; import ; import ; import .*; public class Test { private static final DateTimeFormatter formatter = ("yyyy-MM-dd HH:mm:ss"); private static final ExecutorService threadPool = (16);//It cannot be set to 1 here. It is no longer used to control the number of concurrency, but just to reuse threads private static final ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(1);//The listening timeout, this number must be the same as the number of thread pools public static void main(String[] args) throws Exception { for (int i = 0; i < 10; i++) { (50); // int delay = 3; int delay = i + 1; int k = i; (new Runnable() { @Override public void run() { ScheduledFuture<?> schedule = null; try { (); // Start a timer, if the task is executed for more than 3 seconds, the current thread will be interrupted // If timeoutExecutor only has one thread pool, the code snippets here will be blocked. After the code snippets here of the previous thread are executed, the current thread will execute the code snippets here. // But the impact is not big, because the code snippet here is just a release action and will be executed in an instant, so the impact is not big. // If the blocking time in other scenarios is relatively long, then the timeoutExecutor thread size must be the same as the threadPool thread size. schedule = (() -> { ("Release 1"); (); }, delay, ); ("【" + ().getName() + "】" + ().format(formatter)); (5000); // FileOutputStream fos = new FileOutputStream("d:/" + k); // for (int j = 0; j < 1000000; j++) { // ("123".getBytes()); // } // (); } catch (Exception e) { ("abnormal"); } finally { if (schedule != null) { //Cancel returns true task has not been executed yet, and the task needs to be canceled if ((true)) { ("Release 2"); (); } } } } }); } } }
package ; import ; import ; import ; import ; /** * Thread pool */ public class ThreadPool { private static final int MAX_POOL_SIZE = 1; // Maximum number of threads, control the number of concurrency private static int totalThread = 0; // Total number of threads private static final Lock lock = new ReentrantLock(true); private static final Condition notice = (); /** * Get thread from thread pool */ public static boolean awaitThread() { (); try { // Try to get threads from thread pool if (totalThread < MAX_POOL_SIZE) { totalThread++; return true; } // The thread has reached the maximum number of threads, waiting for the return thread, waiting for up to 1 hour, await() will release the lock of the current thread if ((1, )) { totalThread++; return true; } } catch (Exception e) { (); } finally { (); } return false; } /** * Free thread to thread pool */ public static void releaseThread() { (); try { totalThread--; // If there is any free notification, signal() will wake up one of the await() threads. (); } finally { (); } } }
This is the article about the summary of the Java thread pool ExecutorService timeout processing. For more related content on the Java thread pool ExecutorService timeout, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!