2

My teacher told me not to use stop() but to use this way in the Thread class:

public void pararHilo() { 
    stopHilo = true; 
}

public void run() {
    while (!stopHilo) 
        c++; 
} 

As far as I know, when pararHilo() is called the loop ends, therefore it exits the run() method and the Thread dies. The thing is that I have a pretty decent laptop and when doing tests with this code (here and at school) my machine gets laggy as hell and I have to close Eclipse... Am I missing something?

Whole code

public class EjemploHilo { 

    public static void main(String args[]) { 

        HiloPrioridad h1 = new HiloPrioridad(); 
        HiloPrioridad h2 = new HiloPrioridad();
        HiloPrioridad h3 = new HiloPrioridad();

        //el hilo con mas prioridad contara mas deprisa que los demas
        h1.setPriority(Thread.MAX_PRIORITY); 
        h2.setPriority(Thread.NORM_PRIORITY);
        h3.setPriority (Thread.MIN_PRIORITY); 

        h1.start(); h2.start(); h3.start();

        try { 
            Thread.sleep(2000); 
            } catch (Exception e) { } 

        h1.pararHilo(); 
        h2.pararHilo(); 
        h3.pararHilo(); 

        System.out.println("h1 (Prioridad Maxima): " + h1.getContador()); 
        System.out.println("h2 (Prioridad Normal): " + h2.getContador()); 
        System.out.println("h3 (Prioridad Minima): " + h3.getContador());

        } 

}

public class HiloPrioridad extends Thread { 

    private int c = 0; 
    private boolean stopHilo= false; 

    public int getContador() {
        return c; 
    }

    public void pararHilo() { 
        stopHilo = true; 
    }

    public void run() {
        while (!stopHilo) 
            c++; 
    } 

}
blacktide
  • 10,654
  • 8
  • 33
  • 53
Artur Alvaro
  • 115
  • 8
  • could you please show more code? in general, you should probably sleep in between executions, or, more elegantly, have a look at the java concurrency package and executors. – rmalchow Feb 26 '16 at 01:22
  • Yes, this is OK. The reason that your machine is getting `laggy` is that you are running to very tight loop which will loop madly using 100% CPU. Consider adding a `Thread.sleep (100)` into your loop – Scary Wombat Feb 26 '16 at 01:23
  • Thread.sleep(10) would probably be enough to get back a decent performance. – Jean-François Savard Feb 26 '16 at 01:25
  • http://stackoverflow.com/questions/10961714/how-to-properly-stop-the-thread-in-java – JavaHopper Feb 26 '16 at 01:25
  • Could you please show is the declaration for `stopHilo` variable, as if not declared as volatile its going to become tricky in accessing the threads, and possibly causing the lag. – Conner Feb 26 '16 at 01:25
  • A thread like this can only be stopped with `Thread.stop()`, which is deprecated. The best way is to use `Thread.interrupt()`. If you do IO this happens automatically. Or else you have to check periodically for `Thread.interrupted()`. – markspace Feb 26 '16 at 01:25
  • Thanks guys, the Thread.sleep(10) solution worked just great – Artur Alvaro Feb 26 '16 at 01:39

4 Answers4

3

Your while loop should check for the following:

while (!Thread.currentThread().isInterrupted() && /* more work to do */) {
    // do more work
}

This way, a client can call Thread.interrupt(), which sets the interrupted status of the thread to true.

Note: When the interrupt method is called on a thread that blocks on a call such as sleep or wait, the blocking call is terminated by an InterruptedException, which should be handled:

try {
    while (!Thread.currentThread().isInterrupted() && /* more work to do */) {
        // do more work
        Thread.sleep(1000);
    }
} catch (InterruptedException e) {
    // thread was interrupted during sleep or wait
}
blacktide
  • 10,654
  • 8
  • 33
  • 53
  • 1
    just got to that exception, checked documentation and was about to comment that same thing, thanks for the alternative way to handle the issue – Artur Alvaro Feb 26 '16 at 01:47
  • @Artur: this is the correct way to do it. the make-your-own-flag way has problems where the thread can't wake from sleep or wait, and cases where you build threadsafe structures that include components like those in java.util.concurrent (that can't know about your flag) aren't handled. – Nathan Hughes Feb 26 '16 at 02:19
1

Yes, but you need the semaphore variable to be to volatile:

private volatile stopHilo;

otherwise the running thread may never see the assignment.

Also, a tight loop like that should pause Thread.sleep() or yield Thread.yield() periodically.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

The use of a request variable for stopping a thread is only suitable if the variable can be polled at a high rate.

If you are calling methods such as Thread.sleep() or waiting on other procedures then your program is going to slow down and a high rate of polling for the request variable is not suitable.

Instead use Thread.interrupt() to stop the thread.

You may find Oracle's guide to why Thread.stop was deprecated helpful.

Another issue you may be facing is that the Thread request variable is not volatile ensure you have declared it for intended use.

private volatile boolean stopHilo = false;
Conner
  • 177
  • 2
  • 7
  • 18
0

I think you need to be careful with the following things:

1) Thread priority. You have one of your sub threads set as HIGH_PRIORITY whereas your main thread isn't set and so it should be using normal. As a result, one of your sub-threads has higher priority than your main thread. Since you have an endless loop, that will be sucking up a lot of your CPU while your main thread could be waiting (since it is a lower priority).

2) Like others have said, I would put even a small sleep in your sub-thread run method loop. This will give the main thread (and others) time to execute.

3) I also personally do not refer directly to the variable just in practice. Typically, I would use a get method even in the while loop that goes and returns the variable. This is just a standard coding practice that is typically used. If this get/set methods are important to threading, then you can also make them synchronized. In this way, a set can't happen in that millionth of a second that a get is happening and vice versa. One extra protection (depending on your app usage). As all topics, these types of decisions need to be made on a case-by-case basis but it is something to consider. You can still call pararHilo and have that call the set method or your main thread could just call the setStopHilo(false).

Can you give those 3 things a try and see how it works for you?

BoBoCoding
  • 161
  • 1
  • 4