Ticker

6/recent/ticker-posts

Ad Code

Responsive Advertisement

How to stop/kill long running Java Thread at runtime? timed-out -> cancelled -> interrupted states

How to Kill Java Thread Taking Longer than Expected to Finish? timedout -> cancelled -> interuppted state

Have you ever wondered how to kill long running Java thread? Do you have any of below questions?

  • Kill/Stop a thread after certain period of time
  • Killing thread after some specified time limit in Java
  • How to Kill a Java Thread
  • How To Stop A Thread In Java With An Example
  • how to stop thread in java code example
  • how to stop a thread in java without using stop method

If you have any of below questions then you are at right place. Today we will go over simple example which demonstrates Java8 ways to kill long running thread.

What is a Logic:

  1. Create class CrunchifyJavaTaskTimeout.java
  2. Create Java Thread executor with only 1 threadpool size.
  3. Create 4 future tasks of a CrunchifyRunner object with timeout of 3 seconds
  4. CrunchifyRunner.java is a simple class which implements call() method
    • It introduces 20 seconds delay if futureTask = 4
  5. Once future hits 3 seconds time it creates timeout Exception if thread is still running
    • Once it’s timed-out we need to cancel task using crunchifyFuture.cancel(true);
    • Once futureTask is cancelled it will trigger InterruptedException (Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. Occasionally a method may wish to test whether the current thread has been interrupted, and if so, to immediately throw this exception.)

Let’s get started:

Step-1 Create CrunchifyRunner.java class

package crunchify.java.tutorials;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Callable;

/**
 * @author Crunchify.com 
 * Version: 1.0.1
 * 
 */

public class CrunchifyRunner implements Callable<Boolean> {

        private int workerNumber;

        public int getNumber() {
                return workerNumber;
        }

        public void setNumber(int workerNumber) {
                this.workerNumber = workerNumber;
        }

        public CrunchifyRunner(int workerNumber) {
                this.workerNumber = workerNumber;
                setNumber(workerNumber);
        }

        SimpleDateFormat crunchifyFormatter = new SimpleDateFormat("dd-MMMMM-yyyy hh:mm:ss");

        public Boolean call() throws InterruptedException {
                try {
                        if (workerNumber == 4) {

                                // Sleep for 20 Seconds to generate long running thread.
                                Thread.sleep(20000);
                        } else {
                                Thread.sleep(50);
                        }
                } catch (InterruptedException ie) {
                        log("\n" + crunchifyFormatter.format(new Date()) + " crunchifyWorker task " + workerNumber + " interrupted.");
                        log("\n=======> Basically once thread is timed out, it should be cancelled and interrupted. (timedout ==> cancelled ==> interrupted)");
                }

                // Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. Occasionally a
                // method may wish to test whether the current thread has been interrupted, and if so, to immediately throw this exception.
                return true;
        }

        public void log(String info) {
                System.out.println(info);

        }
}

Step-2 Create class CrunchifyJavaTaskTimeout.java

package crunchify.java.tutorials;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @author Crunchify.com 
 * Version: 1.0.2
 * 
 */

public class CrunchifyJavaTaskTimeout {

        @SuppressWarnings({ "rawtypes", "unchecked" })

        public static void main(final String[] args) {

                // Creates an ExecutorCompletionService using the supplied executor for base task execution and a LinkedBlockingQueue as a completion queue.
                CompletionService<Boolean> crunchifyService = new ExecutorCompletionService<Boolean>(Executors.newFixedThreadPool(1));

                Collection<CrunchifyRunner> crunchifyThreads = new ArrayList<CrunchifyRunner>(50);

                crunchifyThreads.add(new CrunchifyRunner(1));
                crunchifyThreads.add(new CrunchifyRunner(2));
                crunchifyThreads.add(new CrunchifyRunner(3));
                crunchifyThreads.add(new CrunchifyRunner(4));

                SimpleDateFormat crunchifyFormatter = new SimpleDateFormat("dd-MMMMM-yyyy hh:mm:ss");

                List<Future<Boolean>> crunchifyFutures = new ArrayList<Future<Boolean>>(crunchifyThreads.size());
                try {

                        // Let's first add all tasks to future
                        for (Callable crunchifyTask : crunchifyThreads) {

                                crunchifyFutures.add(crunchifyService.submit(crunchifyTask));
                        }
                        for (int count = 1; count <= crunchifyFutures.size(); count++) {

                                // Let's put Future timeout to 3 Seconds
                                Future<Boolean> crunchifyResult = crunchifyService.poll(3000, TimeUnit.MILLISECONDS);
                                if (crunchifyResult == null) {

                                        log(crunchifyFormatter.format(new Date()) + "\n ==> crunchifyWorker task " + count + " timedout.");

                                        // So lets cancel the first futures we find that haven't completed
                                        for (Future crunchifyFuture : crunchifyFutures) {
                                                if (crunchifyFuture.isDone()) {
                                                        continue;
                                                } else {
                                                        crunchifyFuture.cancel(true);
                                                        log(" ==> crunchifyWorker task " + count +" cancelled.");
                                                        break;
                                                }
                                        }
                                        continue;
                                } else {
                                        try {
                                                if (crunchifyResult.isDone() && !crunchifyResult.isCancelled() && crunchifyResult.get()) {
                                                        log(crunchifyFormatter.format(new Date()) + " ==> crunchifyWorker task " + count + " completed.");

                                                } else {
                                                        log(crunchifyFormatter.format(new Date()) + " ==> crunchifyWorker task failed");
                                                }
                                        } catch (ExecutionException exception) {
                                                log(exception.getMessage());
                                        }
                                }
                        }
                } catch (InterruptedException exception) {

                        // Log exception message
                        log(exception.getMessage());
                } finally {

                        // Cancel by interrupting any existing tasks currently running in Executor Service
                        for (Future<Boolean> future : crunchifyFutures) {
                                future.cancel(true);
                        }
                }
                log("\n=======> All tasks completed. Now long running thread 4 should be interrupted immediately after this.");
                System.exit(0);
        }

        private static void log(String string) {
                System.out.println(string);

        }

}

Step-3

Right click on CrunchifyJavaTaskTimeout.java and run it as a Java Application.

You will see below result in Eclipse console.

How to kill stop java thread at runtime

27-November-2018 10:32:29 ==> crunchifyWorker task 1 completed.
27-November-2018 10:32:29 ==> crunchifyWorker task 2 completed.
27-November-2018 10:32:29 ==> crunchifyWorker task 3 completed.
27-November-2018 10:32:32
 ==> crunchifyWorker task 4 timedout.
 ==> crunchifyWorker task 4 cancelled.

=======> All tasks completed. Now long running thread 4 should be interrupted immediately after this.

27-November-2018 10:32:32 crunchifyWorker task 4 interrupted.

=======> Basically once thread is timed out, it should be cancelled and interrupted. (timedout ==> cancelled ==> interrupted)

Let me know if you have any questions on this topic.

The post How to stop/kill long running Java Thread at runtime? timed-out -> cancelled -> interrupted states appeared first on Crunchify.

Enregistrer un commentaire

0 Commentaires