0

I have a Java GUI application based on JFrame, which uses a Java Class that controls multiple Java Threads:

enter image description here

I'm trying to control any thread from Control Class to

  1. Terminate a thread
  2. Suspend a thread
  3. Un-suspend a thread

So far, Control Class can create a thread and add it to ArrayList to keep track of all created threads:

public class Control 
{
ArrayList<myThread> threads;
int counter;

Control()
{
    // do construction work..
}

int createThreadAndRun(String keyword)
{
    // create an instance of myThread:
    counter++;

    myThread mythread       = new myThread( keyword, counter);
    mythread.runnable       = true;
    mythread.start();

    // add it to ArrayList:
    threads.add(mythread);

    return counter;
}

boolean suspendByID( int id )
{
    // loop over all threads in array:
    for( myThread t : threads )
    {
        if( t.id == id && t.runnable == true )
        {
            t.runnable = false;
            return true;
        }
    }
    return false;
}

boolean unsuspendByID( int id ) 
{
    for( myThread t : threads )
    {
        if( t.id == id && t.runnable == false )
        {
            synchronized(t)
            {
                t.runnable = true;
                t.notify();
            }
            System.out.println("Thread "+id+" Unsuspended.");
            return true;
        }
    }
    return false;
}

boolean terminateByID( int id )
{
    for( myThread t : threads )
    {
        if( t.id == id && t.terminated == false )
        {
            synchronized(t)
            {
                t.terminated = true;
                if( !t.isAlive() )
                    t.notify();
            }
            System.out.println("Thread "+id+" terminated.");
            return true;
        }
    }
    return false;
}

void terminateAll() 
{
    for( myThread t : threads )
    {
        if( t.terminated == false )
        {
            synchronized(t)
            {
                t.terminated = true;
                if( !t.isAlive() )
                    t.notify();
            }
        }
    }
}
}

And here is the logic of myThread Class:

class myThread extends Thread
{
        protected volatile boolean runnable     = false;
        protected volatile boolean terminated   = false;

        Logger log;


        myThread(String keyword, int id)
        {
            // constrcution work ..
            log             = new Logger();
        }

        @Override
        public  void run()
        {   
            synchronized(this)
            {
                while(!terminated )
                {
                    // do some work ... 

                    this.wait(10000);

                    if(runnable == false)
                    {
                        System.out.println("Thread "+id+" is suspended.");
                        this.wait();
                    }
                }

                log.close();
                System.out.println("Thread terminated.").
            }
        }
    }

My question is twofold:

1) The way I control the threads in Control Class, is it the right/best practice way?

2) I want to override formWindowClosing() method in my GUI so that it terminates all threads like this:

private void formWindowClosing(java.awt.event.WindowEvent evt) {                                   

        // Terminate all threads and close all open files from Logger:
        ret.terminateAll();


        System.exit(0);

    } 

Is this also best practice/the right way? Currently, when the JForm is closed, the statements at the end of myThread class:

log.close();
System.out.println("Thread terminated.").

are not executed at all. I think System.exit(0) should wait until all threads finish running/terminated, but how??

Nicholas Sizer
  • 3,490
  • 3
  • 26
  • 29
Jarvis
  • 117
  • 1
  • 1
  • 10

2 Answers2

0

I found a solution to Question 2:

I added a join() statement inside the void terminateAll() method:

void terminateAll() 
{
    for( myThread t : threads )
    {
        if( t.terminated == false )
        {
            synchronized(t)
            {
                t.terminated = true;
                if( !t.isAlive() )
                    t.notify();
                t.join() // blocks the execution until t finishes.
            }
        }
    }
}
Jarvis
  • 117
  • 1
  • 1
  • 10
0

Consider using interrupt() instead of notify(). If your thread workload involves I/O, interrupting it will get those operations to terminate early.

Bob Jacobsen
  • 1,150
  • 6
  • 9
  • I used "notify()" in the "terminateAll()" method to wake up the current thread (in case it was waiting/suspended) so that it can finish its work and terminate. – Jarvis Mar 31 '18 at 17:47
  • Read about `interrupt` here: https://stackoverflow.com/questions/30471285/what-is-the-difference-between-wait-notify-and-wait-interrupt?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa – Bob Jacobsen Mar 31 '18 at 18:03