user3608212
user3608212

Reputation: 31

How to identify and restart the threads that have been killed after starting a list of threads using the java class?

I have started 20 threads in my class, each thread will run in a loop to do something

for(int i=1;i<=20;i++) {
    MyThread mt = new MyThread(i);                  
    Thread t = new Thread(mt);
    t.start();
}

MyThread.java

public class MyThread implements Runnable{
    private int threadId;
    public MyThread(int i) {
        this.threadId = i;
    }
    @Override
    public void run() {
        if(threadId > 0) {
            while(1) {
                try {
                    //do something
                } catch(Exception ex) {
                    //do nothing
                }
            }
        }
    }
}

Now I want to monitor each thread and if anyone of them stops, I want to start a new thread with the corresponding threadId. How can I do that? Please help me.

Upvotes: 1

Views: 146

Answers (2)

David K&#252;hner
David K&#252;hner

Reputation: 803

I'll start with the possible states of the Thread class. There are 6 possible states:

Enum Thread.State

NEW : A thread that has not yet started is in this state.

RUNNABLE : A thread executing in the Java virtual machine is in this state.

BLOCKED : A thread that is blocked waiting for a monitor lock is in this state.

WAITING : A thread that is waiting indefinitely for another thread to perform a particular action is in this state.

TIMED_WAITING : A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.

TERMINATED : A thread that has exited is in this state.

Threads that "has been killed" as you said are those in Terminated state. There are two main causes that will lead to the Terminated state.

  • A) The run() method exits normally after his work.
  • B) Exception occurs and run() method ended.

If you want that your Threads "never" go in Terminated mode then you should A) have an infinite loop B) catch all exceptions. But that was not exactly your question. How to monitor the state of the Threads?

Key is the getState() method

public Thread.State getState()

Returns the state of this thread. This method is designed for use in monitoring of the system state, not for synchronization control.

You can do what you want with the following 3 classes:

App.java

package com.what.ever;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class App {

    private static int MONITORING_FREQUENCY = 5;
    private static int NUMBER_OF_TASKS = 3;

    public static void main(String[] args) {
        List<ThreadMonitor> threadMonitors = initThreadMonitors();

        threadMonitors.forEach(m -> m.printState());
        threadMonitors.forEach(m -> m.startThread());

        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(() -> threadMonitors.forEach(m -> m.restartIfTerminated()), MONITORING_FREQUENCY, MONITORING_FREQUENCY, TimeUnit.SECONDS);
    }

    private static List<ThreadMonitor> initThreadMonitors() {
        List<ThreadMonitor> threadMonitors = new ArrayList<>();

        for (int i = 1; i <= NUMBER_OF_TASKS; i++) {
            DummyRunnable runnable = new DummyRunnable(i);
            ThreadMonitor threadMonitor = new ThreadMonitor(runnable);
            threadMonitors.add(threadMonitor);
        }

        return threadMonitors;
    }
}

ThreadMonitor.java

package com.what.ever;

public class ThreadMonitor {

    private Thread thread;
    private DummyRunnable runnable;

    public ThreadMonitor( DummyRunnable runnable) {
        this.runnable = runnable;
        this.thread = new Thread(runnable);
    }

    public boolean startThread() {
        boolean isStarCalled = false;
        if(Thread.State.NEW.equals(thread.getState())) {
            thread.start();
            isStarCalled = true;
        }
        return isStarCalled;
    }

    public void printState() {
        System.out.println( thread.toString() + " is in state : " + thread.getState());
    }

    public void restartIfTerminated() {
        printState();
        if(Thread.State.TERMINATED.equals(thread.getState())) {
            thread = new Thread(runnable);
            thread.start();
        }
    }
}

DummyRunnable.java

package com.what.ever;

public class DummyRunnable implements Runnable {

    private int id;

    public DummyRunnable(int id) {
        this.id = id;
    }

    public void run() {
        System.out.println("Runnable " + id + " started in thread: " + Thread.currentThread());
        dummyWork();
        System.out.println("Runnable " + id + " done");
    }

    private void dummyWork() {
        int sleep = 10000;
        if (id == 3) {
            sleep = 1000;
        }
        try {
            Thread.sleep(sleep);
        } catch (Exception e) {
            System.out.print(e);
        }
    }
}

Here you go. If you have any question about this example, just ask.

Small warnings: Be careful with the monitoring frequency, it can have huge impact on the performances. Don't try to do real time application with this.

Upvotes: 2

edharned
edharned

Reputation: 1904

If you want to test threads then keep a list of threads in an array:

MyThread[] mt = new MyThread[20];
...
mt[i] = ...

Now you can inquire on each thread with methods from the Thread Class, for instance: isAlive();

Upvotes: 0

Related Questions