2

I have created sample program of java Thread in which i am using stop() method to stop the thread using below program

public class App extends Thread
{
    Thread th;

    App(String threadName)
    {
        th = new Thread(threadName);
    }

    public synchronized void run() // Remove synchronized
    {
        for (int i = 0; i < 5; i++) {
            System.out.println(th.getName()+" "+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main( String[] args ) 
    {
       App thread_1 = new App("Thread-1");
       thread_1.start();
       thread_1.setPriority(MAX_PRIORITY); //Comment this
       thread_1.stop();
       App thread_2 = new App("Thread-2");
       thread_2.start();
    }
}

The output of the above program is :

Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4

i.e. thread_1 is not stopped. When i am removing synchronized or priority in the code thread is stopped immediately and output will be

Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4

I am not able to understand why it is working like this.

Kick
  • 4,823
  • 3
  • 22
  • 29
  • 1
    [`Thread#stop`](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#stop()) is deprecated - *"This method is inherently unsafe. ..."*. You should consider using some kind of [locking mechanism](http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html) instead – MadProgrammer Jan 21 '15 at 05:49
  • @MadProgrammer I know dear,, but for knowledge purpose. Can you help me – Kick Jan 21 '15 at 05:50
  • No, the functionality of the `stop` method is undefined, that's the problem. Use some kind of locking mechanism instead. – MadProgrammer Jan 21 '15 at 05:51
  • 1
    Why do you think that thread_1 does not stop? thread_1.join will wait until thread_1 exits. And as thread_2 did start, this means that join unblocks and so thread_1 really stopped. – Nikem Jan 21 '15 at 05:57
  • @Nikem If you remove join(), output will be same – Kick Jan 21 '15 at 05:58
  • Still, why do you think that thread_1 does not stop? I don't see any indication of that from your output. What is your reasoning? – Nikem Jan 21 '15 at 05:59
  • @Nikem See my updation in question – Kick Jan 21 '15 at 06:03
  • The basic reason why people have been asking you not to use stop because, it does not follow a cut and dried logic and is darn inconsistent. From that perspective, answering the question becomes a bit difficult . Its pretty difficult to stop a thread when it's inside the synchronized method . Use this Link : http://www.forward.com.au/javaProgramming/HowToStopAThread.html to understand it more. Hence , it is better to use a volatile variable or other ways of doing it as reported in the tutorial to do so . – The Dark Knight Jan 21 '15 at 07:26
  • What is the purpose of the instance variable, `th`, in your App class? The constructor assigns a new Thread instance to it, but that Thread is never used anywhere. – Solomon Slow Jan 21 '15 at 20:06

4 Answers4

5

Most of the public methods of the Thread class are synchronized on the Thread instance itself. http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/5672a2be515a/src/share/classes/java/lang/Thread.java

Your run() method is synchronized on the Thread instance. The stop() method calls stop(Throwable), which is also synchronized on the Thread instance, its signature is:

@Deprecated
public final synchronized void stop(Throwable obj) {

The synchronization prevents the main thread from entering thread_1.stop() while the thread itself is still running in your synchronized run() method.


This is an example of why it's wise to always use private objects for synchronization. E.g., do this...

class Foobar {
    private final Object lock = new Object();

    public void do_something() {
        synchronized(lock) {
            ...
        }
    }
}

Instead of doing this...

class Foobar {
    public synchronized void do_something() {
        ...
    }
}

The second version is more verbose (Welcome to Java!), but it prevents the user of your Foobar class from using it as a synchronization object in a way that interferes with its own use of itself as a synchronization object.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
  • 1
    Avoiding synchronizing on the Thread instance is the big issue. an alternative to using a private lock here would be moving the run method into a Runnable and synchronizing on that instead. – Nathan Hughes Jan 21 '15 at 21:07
  • @NathanHughes, Perhaps my footnote about private locks was ambiguous. I did not mean to say that the OP should have a private lock in the App class: What I really meant was that, IMO, that the Thread class itself should be implemented with (a) private lock object(s) instead of synchronizing on, waiting on, and notifying client-visible instances. – Solomon Slow Jan 21 '15 at 21:26
1

Thread.stop() is deprecated. consider using this instead:

public class App extends Thread
{
    Thread th;
    volatile boolean bStopThread;
    App(String threadName)
    {
        th = new Thread(threadName);
        bStopThread = false;
    }

    public void stopThread(){
        bStopThread = true;
    }

    public synchronized void run() // Remove synchronized
    {
        for (int i = 0; i < 5; i++) {
            if(bStopThread) return;
            System.out.println(th.getName()+" "+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main( String[] args ) throws InterruptedException
    {
       App thread_1 = new App("Thread-1");
       thread_1.start();
       thread_1.setPriority(MAX_PRIORITY); //Comment this
       thread_1.stopThread();
       App thread_2 = new App("Thread-2");
       thread_2.start();
    }
}

It should works as you want, although I haven't tested.

markhc
  • 659
  • 6
  • 15
  • If you use Thread#interrupt instead of rolling your own flag, it will be more responsive; if the thread is busy sleeping it will return from sleep immediately, see [this example](http://stackoverflow.com/a/5915306/217324) – Nathan Hughes Jan 21 '15 at 20:19
0

You have 3 threads in your application: main thread, running the code of the main method, thread_1 and thread_2. Your main thread starts thread_1 at some point in time X, then calls thread_1.stop() in some point in time Y, Y>X.

Now, what can happen between points X and Y, is that CPU scheduler can decide: "I will now let thread_1 run". Thread_1 will get CPU, will run and will print his text. OR, CPU scheduler can decide: "main thread is now running... let it run". And thread_1 will not get CPU until stop is called and will print nothing.

So you have uncertainty outside of your control about CPU scheduling. You can only assume that raising the priority of the thread hints scheduler to pick the first of the aforementioned choices.

But. stop is deprecated, so never use that. And don't try to guess the order of the execution of the multiple threads.

Nikem
  • 5,716
  • 3
  • 32
  • 59
  • Don't think this is right as thread 2 sleeps. I have read the javadocs too but used stop. Example when a jsp is running more than 10 minutes due to a funny regex. See my old questions for more info. Stop is deprecated but never removed. Need it for last resort when u r not in control of a thread – tgkprog Jan 21 '15 at 06:23
  • Fix funny regex. Don't use stop if you want any way of clear reasoning about your application. – Nikem Jan 21 '15 at 06:25
  • Well in our use case, it was part of a site where the email validation for one screen, the regex we were using was causing the java regex to go in to a never ending seq for some emails (never did figure out what) as a quick solutiuon we had to stop threads or the CPU usage would be at 99% http://stackoverflow.com/questions/12258589/jstack-output-get-tid-for-java-thread-getid – tgkprog Jan 21 '15 at 10:17
0

Put a try catch in your main method. Print stack trace and message of caught exception. Same in run method. Then java will tell you issue.

MHC's method is better but like I said - sometimes (rarely) when you have no control over the thread, can only call stop. But in this case you do have control over it so MHC method will work nicely.

But I do not see what is the issue with your code - it runs fine in my laptop, maybe you did not clean and re compile? Chane some message so you know latest code is running

I used :

package academic.threads;

public class StopThHighPri extends Thread {
    Thread th;
    volatile boolean bStopThread;

    StopThHighPri(String threadName) {
        th = new Thread(threadName);
        bStopThread = false;
    }

    public void stopThread(Thread t) {
        //bStopThread = true;
        try {
            t.stop();
        } catch (Throwable e) {
            System.err.println(" Stop th " + e + " " + e.getMessage());
        }
    }

    public synchronized void run() // Remove synchronized
    {
        try {
            for (int i = 0; i < 5; i++) {
                if (bStopThread)
                    return;
                System.out.println(th.getName() + " " + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("run err " + e);
        }
    }

    public static void main(String[] args) {
        try {
            System.err.println("Code version 002");
            StopThHighPri thread_1 = new StopThHighPri("Thread-1");
            thread_1.start();
            thread_1.setPriority(MAX_PRIORITY); // Comment this
            thread_1.stopThread(thread_1);
            StopThHighPri thread_2 = new StopThHighPri("Thread-2");
            thread_2.start();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("MNain err " + e);
        }
    }
}

Put something like System.err.println("Code version 002");

and change the 002 , 003. so you know latest code is working every time you edit the class. Again for learning this is okay but do not need to use stop here

tgkprog
  • 4,493
  • 4
  • 41
  • 70
  • Where try catch, method is not throwing any exception dear. If you can help me it will b better – Kick Jan 21 '15 at 06:24