From 3f78a1e9c0f0763659906c6c17c687f58a5892f2 Mon Sep 17 00:00:00 2001 From: andresluzu Date: Tue, 19 Apr 2022 22:02:34 -0500 Subject: [PATCH] BAEL-4559 Stop Execution After Certain Time improvements (#12076) --- .../stopexecution/FixedTimeTask.java | 28 ++++++ .../stopexecution/LongRunningTask.java | 21 ++++ .../concurrent/stopexecution/Step.java | 23 +++++ .../concurrent/stopexecution/SteppedTask.java | 31 ++++++ .../stopexecution/StoppingExecution.java | 95 +++++++++++++++++++ .../concurrent/stopexecution/TimeOutTask.java | 22 +++++ .../stopexecution/FixedTimeTaskUnitTest.java | 18 ++++ .../LongRunningTaskUnitTest.java | 19 ++++ .../stopexecution/SteppedTaskUnitTest.java | 26 +++++ .../stopexecution/TimeOutTaskUnitTest.java | 20 ++++ 10 files changed, 303 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/FixedTimeTask.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/LongRunningTask.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/Step.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/SteppedTask.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/StoppingExecution.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/TimeOutTask.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/FixedTimeTaskUnitTest.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/LongRunningTaskUnitTest.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/SteppedTaskUnitTest.java create mode 100644 core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/TimeOutTaskUnitTest.java diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/FixedTimeTask.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/FixedTimeTask.java new file mode 100644 index 0000000000..9ac20d73dd --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/FixedTimeTask.java @@ -0,0 +1,28 @@ +package com.baeldung.concurrent.stopexecution; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.TimeUnit; + +public class FixedTimeTask implements Runnable { + + private static final Logger LOG = LoggerFactory.getLogger(FixedTimeTask.class); + + final int fixedTime; // milliseconds + + public FixedTimeTask(int fixedTime) { + this.fixedTime = fixedTime; + } + + @Override + public void run() { + LOG.info(fixedTime + " milliseconds running task"); + try { + TimeUnit.MILLISECONDS.sleep(fixedTime); + } catch (InterruptedException e) { + LOG.info("interrupted"); + } + LOG.info("finished"); + } +} diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/LongRunningTask.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/LongRunningTask.java new file mode 100644 index 0000000000..7167859308 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/LongRunningTask.java @@ -0,0 +1,21 @@ +package com.baeldung.concurrent.stopexecution; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LongRunningTask implements Runnable { + + private static final Logger LOG = LoggerFactory.getLogger(LongRunningTask.class); + + @Override + public void run() { + LOG.info("running"); + for (int i = 0; i < Long.MAX_VALUE; i++) { + if (Thread.interrupted()) { + LOG.info("stopping"); + return; + } + } + LOG.info("finished"); + } +} diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/Step.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/Step.java new file mode 100644 index 0000000000..d6d8c8c036 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/Step.java @@ -0,0 +1,23 @@ +package com.baeldung.concurrent.stopexecution; + +import java.util.Random; + +public class Step { + + private static int MAX = Integer.MAX_VALUE / 2; + int number; + + public Step(int number) { + this.number = number; + } + + public void perform() throws InterruptedException { + Random rnd = new Random(); + int target = rnd.nextInt(MAX); + while (rnd.nextInt(MAX) != target) { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + } + } +} diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/SteppedTask.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/SteppedTask.java new file mode 100644 index 0000000000..5b2b0c445a --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/SteppedTask.java @@ -0,0 +1,31 @@ +package com.baeldung.concurrent.stopexecution; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class SteppedTask implements Runnable { + private static final Logger LOG = LoggerFactory.getLogger(SteppedTask.class); + + private List steps; + + public SteppedTask(List steps) { + this.steps = steps; + } + + @Override + public void run() { + LOG.info("running stepped process"); + for (Step step : steps) { + LOG.info("running step " + step.number); + try { + step.perform(); + } catch (InterruptedException e) { + LOG.info("interrupting task"); + return; + } + } + LOG.info("stepped process finished"); + } +} diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/StoppingExecution.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/StoppingExecution.java new file mode 100644 index 0000000000..ac4af8adc4 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/StoppingExecution.java @@ -0,0 +1,95 @@ +package com.baeldung.concurrent.stopexecution; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Timer; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class StoppingExecution { + + private static final Logger LOG = LoggerFactory.getLogger(StoppingExecution.class); + + public static void main(String[] args) { + StoppingExecution.testUsingLoop(); + StoppingExecution.testUsingTimer(); + StoppingExecution.testUsingFuture(); + StoppingExecution.testScheduledExecutor(); + StoppingExecution.testSteppedProcess(); + } + + public static void testUsingLoop() { + LOG.info("using loop started"); + long start = System.currentTimeMillis(); + long end = start + 30 * 1000; // 30 seconds + while (System.currentTimeMillis() < end) { + LOG.info("running task"); + new FixedTimeTask(7 * 1000).run(); // 7 seconds + } + LOG.info("using loop ended"); + } + + public static void testUsingTimer() { + LOG.info("using timer started"); + Thread thread = new Thread(new LongRunningTask()); + thread.start(); + + Timer timer = new Timer(); + TimeOutTask timeOutTask = new TimeOutTask(thread, timer); + + LOG.info("scheduling timeout in 3 seconds"); + timer.schedule(timeOutTask, 3000); + LOG.info("using timer ended"); + } + + public static void testUsingFuture() { + LOG.info("using future started"); + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future future = executor.submit(new LongRunningTask()); + try { + LOG.info("future get with 7 seconds timeout"); + future.get(7, TimeUnit.SECONDS); + } catch (TimeoutException e) { + LOG.info("future timeout"); + future.cancel(true); + } catch (Exception e) { + LOG.info("future exception", e); + } finally { + executor.shutdownNow(); + } + LOG.info("using future ended"); + } + + public static void testScheduledExecutor() { + LOG.info("using future schedule executor started"); + + ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); + Future future = executor.submit(new LongRunningTask()); + Runnable cancelTask = () -> future.cancel(true); + + LOG.info("cancel task in 3 seconds"); + executor.schedule(cancelTask, 3000, TimeUnit.MILLISECONDS); + executor.shutdown(); + LOG.info("using future schedule executor ended"); + } + + public static void testSteppedProcess() { + List steps = Stream.of(new Step(1), new Step(2), new Step(3), new Step(4)).collect(Collectors.toList()); + + LOG.info("stepped process started"); + Thread thread = new Thread(new SteppedTask(steps)); + thread.start(); + + Timer timer = new Timer(); + TimeOutTask timeOutTask = new TimeOutTask(thread, timer); + timer.schedule(timeOutTask, 10000); + } +} diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/TimeOutTask.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/TimeOutTask.java new file mode 100644 index 0000000000..e27e64476e --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/TimeOutTask.java @@ -0,0 +1,22 @@ +package com.baeldung.concurrent.stopexecution; + +import java.util.Timer; +import java.util.TimerTask; + +public class TimeOutTask extends TimerTask { + private Thread thread; + private Timer timer; + + public TimeOutTask(Thread thread, Timer timer) { + this.thread = thread; + this.timer = timer; + } + + @Override + public void run() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + timer.cancel(); + } + } +} diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/FixedTimeTaskUnitTest.java b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/FixedTimeTaskUnitTest.java new file mode 100644 index 0000000000..bbb8d0571a --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/FixedTimeTaskUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.concurrent.stopexecution; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class FixedTimeTaskUnitTest { + + @Test + public void run() throws InterruptedException { + long start = System.currentTimeMillis(); + Thread thread = new Thread(new FixedTimeTask(10)); + thread.start(); + thread.join(); + long end = System.currentTimeMillis(); + assertTrue(end - start >= 10); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/LongRunningTaskUnitTest.java b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/LongRunningTaskUnitTest.java new file mode 100644 index 0000000000..c9bcb75e6d --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/LongRunningTaskUnitTest.java @@ -0,0 +1,19 @@ +package com.baeldung.concurrent.stopexecution; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LongRunningTaskUnitTest { + + @Test + public void run() { + Thread thread = new Thread(new LongRunningTask()); + thread.start(); + assertTrue(thread.isAlive()); + + thread.interrupt(); + assertTrue(thread.isInterrupted()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/SteppedTaskUnitTest.java b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/SteppedTaskUnitTest.java new file mode 100644 index 0000000000..ab9ac2732a --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/SteppedTaskUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.concurrent.stopexecution; + +import org.junit.Test; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.*; + +public class SteppedTaskUnitTest { + + @Test + public void run() throws InterruptedException { + List steps = Stream.of( + new Step(1), + new Step(2), + new Step(3)) + .collect(Collectors.toList()); + + Thread thread = new Thread(new SteppedTask(steps)); + thread.start(); + thread.interrupt(); + thread.join(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/TimeOutTaskUnitTest.java b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/TimeOutTaskUnitTest.java new file mode 100644 index 0000000000..39ec9f7d26 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/stopexecution/TimeOutTaskUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.concurrent.stopexecution; + +import org.junit.Test; + +import java.util.Timer; + +import static org.junit.Assert.assertTrue; + +public class TimeOutTaskUnitTest { + + @Test + public void run() { + Thread thread = new Thread(new LongRunningTask()); + Timer timer = new Timer(); + TimeOutTask timeOutTask = new TimeOutTask(thread, timer); + thread.start(); + timeOutTask.run(); + assertTrue(thread.isInterrupted()); + } +} \ No newline at end of file