Hey guys,

I'm lost in terms of how to get 1 thread to stop another thread by changing one of its values.

Ie

say I've got a JButton which when pressed invokes thread 1.
I've also got another JButton which when pressed stops thread 1 from processing.

I'm lost since if I add a method to the class which thread1 runs and call it from the JButton the local varables are set since they are allocated on the runtime stack.

Not sure if im understanding this at all, but just a question :-)

Recommended Answers

All 8 Replies

A thread start another thread. The thread that was started has a variable (generally a boolean) that is either protected/public or a setter is provided for it. The class also uses a while loop with that boolean as the test. As soon as the boolean is set to false by the first thread, the next time the second thread checks the value the while loop is done and the thread can exit.

That is only one the ways to do it, but it is one of the more common ways for simple threads.

Hmmm, interesting I managed to get that to work but the next problem would be getting that to work with a ThreadPool where I don't know which thread as got the task to execute.

I've got 4 threads running whilst waiting for work to be assigned to them. I assign a task and wait but I call the task by saying

ThreadPoolInstance.executeTask(new x()); where X implements Runnable.

Yes, the idiom that masijade mentioned is one way to handle it. It's recommended that the boolean flag be declared volatile (i.e. volatile boolean canceled=false; ).

Another way is use thread interruption. Here's a pretty good article on that:
http://www.ibm.com/developerworks/java/library/j-jtp05236.html

If your thread pool executor returns a reference to a Future task, you can cancel the task via Future.cancel(true) and gracefully handle the cancellation of your Runnable via the InterruptedException handler.

Ok, Well i've got the following code written but it doesnt behave correctly. When the thread is executed and then forceably stopped, it doesnt stop the counter in the JFrame. However the method returns true which implies it as stopped :S

package threadTest;


import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;


public class ThreadStopSample extends JFrame
              implements ActionListener{

   
   Thread worker=null ;
   MyTestThread a = new MyTestThread(this);
    // Constructor
   ThreadStopSample(){
	// Create a frame with a button and a text field
	GridLayout gl =new GridLayout(2,1);
	this.getContentPane().setLayout(gl);
	JButton myButton = new JButton("Start/Stop Thread");
	myButton.addActionListener(this);
	this.getContentPane().add(myButton);
	this.getContentPane().add(new JTextField());
   }

    public void actionPerformed(ActionEvent e){
    	// If the thread is running, turn the flag to stop it.
    	// Otherwise, start the thread
        if (worker!=null && worker.isAlive()){
        	a.setStopThreadFlag(true);
        }else{
        	a.setStopThreadFlag(false);
        	ThreadPoolManager.getInstance().submit(a);
                System.out.println(ThreadPoolManager.getInstance().submit(a).cancel(true));
        }

    }

  
    public static void main(String[] args) {
	// Create an instance of the frame
	ThreadStopSample myWindow = new ThreadStopSample();
	// Ensure that the window can be closed
	// by pressing a little cross in the corner
	myWindow.setDefaultCloseOperation(
	         WindowConstants.EXIT_ON_CLOSE);

	// Set the frame's size ang make it visible
	myWindow.setBounds(0,0,150, 100);
	myWindow.setVisible(true);
   }

}
/**
     * submits a task so it can be executed
     *
     *@return the result after execution
     */
    public Future<?> submit (Runnable task) {
        Future<?> future;
        synchronized (scheduler) {
            future = scheduler.submit (task);
        }
        return future;
    }
package threadTest;

/**
 *
 * @author John
 */
public class MyTestThread implements Runnable {
    
    private volatile boolean stopThreadFlag = false;
    
    ThreadStopSample parent;
    
    /** Creates a new instance of MyTestThread */
    public MyTestThread(ThreadStopSample instance ) {
        parent = instance;
    }
    
    public void run() {
        try {
            int i=0;
            while (!stopThreadFlag){
                Thread.sleep(10);
                parent.setTitle("i="+i);
                i++;
                
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    
    public void setStopThreadFlag(boolean flag) {
        stopThreadFlag = flag;
    }
    
}

Ok that example prob isn't the best example but either way it doesn't appear to work correctly and still needs the semapore not sure why though.

What if Thread 1 starts thread 2 by sending a request to the threadpool which kicks off thread 2, then thread 2 starts to wait for IO but doesnt get it? The boolean value is then set to shutdown thread 2 from thread 1 but thread 2 won't continue since its in waiting state for I/O

Does that make sence? I dont have the reference to a Thread object since they object was invoked by the executorService. And the sempore can be changed but as no effect since the Thread is waiting for IO.... Any ideas?

Close the IO channel.

I altered your previous example a bit. Perhaps this may help

package threadTest;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;


public class ThreadStopSample extends JFrame
  implements ActionListener{
    
    ExecutorService threadPool;
    Future task;
    
    // Constructor
    public ThreadStopSample(){
        // Create a frame with a button and a text field
        GridLayout gl =new GridLayout(2,1);
        this.getContentPane().setLayout(gl);
        JButton myButton = new JButton("Start/Stop Thread");
        myButton.addActionListener(this);
        this.getContentPane().add(myButton);
        this.getContentPane().add(new JTextField());
        
        threadPool = Executors.newCachedThreadPool();
    }
    
    public void actionPerformed(ActionEvent e){
        // submit new task or cancel current one
        if (task==null){
            task = submit(new MyTestThread(this));
        } else {
            boolean cancelled = task.cancel(true);
            System.out.println("cancelled="+cancelled);
            task=null;
        }
    }
    
    /**
     * submits a task so it can be executed
     *
     *@return Future reference to the task
     */
    public Future<?> submit(Runnable task) {
        return threadPool.submit(task);
    }
    
    class MyTestThread implements Runnable {
        
        ThreadStopSample parent;
        
        /** Creates a new instance of MyTestThread */
        public MyTestThread(ThreadStopSample instance ) {
            parent = instance;
        }
        
        public void run() {
            try {
                int i=0;
                while (true){
                    Thread.sleep(10);
                    parent.setTitle("i="+i);
                    i++;
                }
            } catch (InterruptedException ie){
                parent.setTitle("canceled");
                // be sure to interrupted status
                Thread.currentThread().interrupt();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        // Create an instance of the frame
        ThreadStopSample myWindow = new ThreadStopSample();
        // Ensure that the window can be closed
        // by pressing a little cross in the corner
        myWindow.setDefaultCloseOperation(
          WindowConstants.EXIT_ON_CLOSE);
        
        // Set the frame's size ang make it visible
        myWindow.setBounds(0,0,150, 100);
        myWindow.setVisible(true);
    }    
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.