2

I just want to start and stop the thread when return key is pressed. Here thread is stopped fine but i cant Start that thread again please help. Also explain me the use of volatile keyword .Is it helpful for me to over come this problem.

public class Sync extends Thread{

    public boolean meth= true;
    public void run(){
        while(meth){
            System.out.println("hello");
            try {

                Thread.sleep(1000);
            } catch (InterruptedException ex) {

            }
           }
    }
    public void shutdown(){
       meth=false;
    }
    public void startup(){
        meth=true;
    }



}

MAIN CLASS``

    package com.Sync;

import java.util.Scanner;


public class SyncMain {
    public static void main(String[] arg) throws InterruptedException{
        Sync hi= new Sync();
        hi.start();
        System.out.println("press enter to stop");

        Scanner d= new Scanner(System.in);

        d.nextLine();
        hi.shutdown();
        System.out.println("press enter to start");
        d.nextLine();
        hi.startup();



    }

}

OUTPUT

   run:
press enter to stop
hello
hello
hello
hello

press enter to start

BUILD SUCCESSFUL (total time: 6 seconds)
jaga D sh
  • 81
  • 6
  • (http://stackoverflow.com/questions/106591/do-you-ever-use-the-volatile-keyword-in-java/28235062#28235062) to know more about volatile – sujith s Aug 03 '15 at 04:51

1 Answers1

2

Thread's are not re-entrant, that is, once they exit the run method, they can't be restarted, you need to create a new instance.

One solution would be to create a new instance of Sync and start it, but a better solution, based on you code might, be to use a wait lock to "pause" the thread and the allow it to resume, for example...

public static class Sync implements Runnable {

    private AtomicBoolean keepRunning = new AtomicBoolean(true);
    private AtomicBoolean pause = new AtomicBoolean(false);

    private ReentrantLock lckPause = new ReentrantLock();
    private Condition conPause = lckPause.newCondition();

    public void run() {
        while (keepRunning.get() && !Thread.currentThread().isInterrupted()) {
            while (pause.get() && !Thread.currentThread().isInterrupted()) {
                lckPause.lock();
                try {
                    System.out.println("Paused");
                    conPause.await();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                } finally {
                    lckPause.unlock();
                }
            }
            if (!Thread.currentThread().isInterrupted()) {
                System.out.println("hello");
                try {

                    Thread.sleep(1000);
                } catch (InterruptedException ex) {

                }
            }
        }
    }

    public void setPaused(boolean paused) {
        if (pause.get() != paused) {
            pause.set(paused);
            if (!paused) {
                lckPause.lock();
                try {
                    conPause.signal();
                } finally {
                    lckPause.unlock();
                }
            }
        }
    }

    public void terminate() {
        keepRunning.set(false);
        setPaused(false);
    }

}

This basically sets up two loops, one to keep the thread running until it's "terminated" and one to trap the "pause" condition...

Then you could do something like...

public static void main(String[] args) {
    Sync hi = new Sync();
    Thread t = new Thread(hi);
    t.start();

    Scanner d = new Scanner(System.in);
    System.out.println("press enter to pause");
    d.nextLine();
    hi.setPaused(true);
    System.out.println("press enter to resume");
    d.nextLine();
    hi.setPaused(false);
    System.out.println("press enter to terminate");
    d.nextLine();
    hi.terminate();

    try {
        t.join();
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }

    System.out.println("Has terminated");
}

to simply run it...

You should note that it's generally discouraged to extend directly from Thread and it is generally encouraged to use a separate Runnable, there are many reasons, but one which you will find most useful in future is Runnable is more widely supported in different parts of the API (like the Executors API) making it a much more flexible option

Have a look at the Concurrency Trail for more details, in particular Lock Objects

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366