Java Thread interrupt isAlive Volatile

1.1 Overview

  1. Understand how Java interrupts are implemented
  2. Understand what exceptions are and how to use them with
    interrupts
  3. Understand how to terminate threads
  4. Understand some of the risks of threads and how to mitigate them

1.2 Get a reference to yourself as a thread

Thread.currentThread().interrupt();

1.3 Summary of methods

Thread.sleep(1000)

  • Pauses thread from executing for 1000 milliseconds

myThread.join()
join函数解读

  • Pauses current thread until myThread has finished executing
  • In other words myThread’s run() method has finished
    线程A的run方法中调用了线程B的join,此时线程A处于阻塞状态,直到线程B执行完毕或者死亡的时候,线程A才会继续执行。

myThread.interrupt()

  • send an interrupt signal to myThread
  • This will set myThread’s interrupt flag to true

2.1 What is an interrupt

  1. An interrupt is an indication to a thread that it should stop what it is doing and do sth else.
  2. The programmer decides how a thread responds to an interrupt
  3. A thread sends an interrupt ny invoking interrupt() on the Thread obect to be interrupted.
  4. For the interrupt mechanism to work correctly, the interrupted thread must support it. (check the interrupt flag)

2.2 Interrupt Mechanism

  1. The interrupt mechanism is implemented using an internal flag known as the interrupt status.
  2. Invoking interrupt on a target threads sets this flag
  3. A thread may check for an interrupt by invoking the static method Thread.interrupted()
  4. one thread can query the interrupt status of another by using the non-static isInterrupted().

2.3 The two interrupt methods

  • Thread.interrupted() is static and checks if the current thread has its interrupted flag set to true.
    • only works for the thread that it is called from
    • The interrupt status is then automatically cleared
  • mythread.isInterrupted() is an instance method which checks the Thread object that it is called on.
    • Can be used to check if a different thread is interrupted
    • E.g. if(thread2.isInterrupted() == true)…
  • A common error is to mix these two up

2.4 Check the interrupt flag

MyThread myThread = new MyThread()
if (myThread.isInterrupted())
{
    
    } //Correct syntax
//Example 1
//Doesn’t check the interrupt flag! Just ignores it!
class MyThread extends Thread
{
    
    
    public void run(){
    
    
        for(int i =1;i <=5;i++){
    
    
            System.out.println(i);
        }
    }

    public static void main(String args[]){
    
    
    MyThread t1 = new MyThread();
    t1.start();
    t1.interrupt();
    }
}

??? Reminder: Throw exits directly

try{
    
    ...}
catch (FileNotFoundException e){
    
    
    System.err.println("FileNotFoundException:" + e.getMessage());
    throw new SampleException(e);
}
catch (IOException e){
    
    
    System.err.println("Caught IOException:" + e.getMessage());
}

2.5 InterruptedException

//Example2 Interrupting a thread that stops working
class MyThread extends Thread{
    
    
    public void run(){
    
    
        try{
    
    
            Thread.sleep(1000);
            System.out.println("Finished!"); //Not printed
        }
        catch(InterruptedException e ){
    
    
            //This doesn't really do anything
            System.out.println("I'm interrupted"); //Printed
            System.exit(-1);
            //This should be used to deal with the exception

        }
    }

    public static void main (String args[]){
    
    
        MyThread t1 = new MyThread();
        t1.start();
        try{
    
    
            t1.interrupt();//Wrong Syntax
        }
        catch(Exception e)
        {
    
    
            System.out.println("Exception handled" +e);
        }
    }
}
  • if the thread is sleeping or joining or waiting on another Thread:

      1. InterruptedException is thrown
      1. Interrupted status will be cleared
        Do things to tidy up and finish the thread
  • Restoring the interrupted status

public void run(){
    
     
    while(!Thread.currentThread().isInterrupted())
    {
    
    
        // Doing some heavy operations
        try {
    
    
        Thread.sleep(5000);
        }
        catch(InterruptedException e)
        {
    
    
        Thread.currentThread().interrupt();
        //interrupt again as may need to do something rather than just exit
        }
    }
}

3.Terminating threads

3.1 isAlive()

  1. A thread is said to be alive (where isAlive()returns true )when is has been started and still not died.
  2. isAlive() method returns true if the thread(upon which it is called) is still running and not finished.
  3. The Thread class comes with an instance method isAlive() to determine whether the thread is in born state or dead state where calling isAlive() returns false.
if(myThread.isAlive())
{
    
    
    //check something  
    //myThread.interrupt();
}

The method that you will more commonly use to wait for a thread to finish is called join()

3.2 Terminate a thread (3 ways Overview)

You have no command to force a Thread to stop(in java)

  1. The thread has finished and exits naturally.
  2. The thread has been marked as daemon(后台程序) thread. When the parent thread who created this thread terminates, this hread will be forcefully(有力地) terminated.
  3. The thread has received an interrupt signal, while doing its work.
  • It decides to not continue with work and exits the run() method.
  • It may also decide to ignore the signal and continue to work.

3.3 Finish the thread naturally

  • Or could use a shared Boolean(e.g. pleaseFinish)
    • Periodically check to see if pleaseFinish is set to true
    • If true, finish thread
      挥发性 — volatile
class MyThread extends Thread{
    
    
    private volatile boolean pleaseFinish = false;

    public void run(){
    
    
        //Periodically check for pleaseFinish to be  
        //set to true

        //Do something  
        //Finish nturally  
    }
    public void finishThreadPlease(){
    
    
        pleaseFinish = true;
        /*Be careful when using pleaseFinish  

        If thread is in a non-runnable state, setting a stpo flag variable will have no effect
        
        A thread is in a non-runnale state if  
        + Its sleep method is invoked.
        + The thread calls the wait method to wait for a specific condition to be satisfied.  
        + The thread is blocking on I/O

        */
    }
}

3.4 Daemon Threads

  • Cannot start it and then daemon it.
  • myThread.setDaemon(false)
    The Worker thread continues to run after parent thread has finished.

  • myThread.setDaemon(true)
    Worker thread terminates when the parent thread terminates.

public void run(){
    
    
    WorkerThread t1 = new WorkerThread();
    t1.setDaemon(true);
    t1.start();
    //do sth  
    //this thread completes
    //When this thread completes:
    //t1 will also be terminated(automatically)
}

3.5 Interrupt the thread

You should catch an InterruptedException and then stop the thread

public void run()
{
    
    
    for (int i = 0; i < importantInfo.length; i++)
    {
    
    
        try {
    
     Thread.sleep(4000); }
        catch (InterruptedException e)
        {
    
    return; }
    System.out.println(importantInfo[i]);
    }
}

Routinely check for interrupts at strategic points where you can safely stop and cleanup

if (Thread.currentThread.isInterrupted())
{
    
    // cleanup and stop execution
return;
}
public class InterruptThread {
    
    
public static void main(String[] args) {
    
    
Thread thread1 = new Thread(new WaitRunnable());
thread1.start();
try {
    
     Thread.sleep(1000); } // wait a second to make sure thread1 started
catch (InterruptedException e) {
    
     e.printStackTrace(); }
thread1.interrupt(); } // now interrupt thread1

Example that the interrupted status has been set to false.

private static class WaitRunnable implements Runnable {
    
    
@Override
public void run() {
    
    
System.out.println("Current time millis : " + System.currentTimeMillis());
try {
    
     Thread.sleep(5000); } // will be asleep when interrupt comes
catch (InterruptedException e) {
    
    
System.out.println("The thread has been interrupted");

System.out.println("The thread is interrupted : " + Thread.interrupted(); // the interrupted status has been set to false}

System.out.println("Current time millis :+ System.currentTimeMillis()); } } }

4.1 Volatile

  • Volatile is used to indicate that a variable’s value will
    be modified by different threads
  • Access to the variable is only given to one thread at a
    time
    public volatile int counter = 0;

4.2 Common traps with volatile

Array
If you declare arr[] as volatile, that means that

  1. the reference to the array is volatile;
  2. individual field accesses (e.g. arr[5]) are not thread‐safe

Unary operations
(++, ‐‐) aren’t atomic

volatile int i; 
... 
i += 5; //NOT SAFE

4.3 Usage: Stop Caching

If a variable is modified, another thread’s cache may go out‐of‐date
If you set a variable to volatile:

  1. The value of this variable will never be cached thread‐locally
  2. All reads and writes will go straight to “main memory”;
public class StoppableTask extends Thread {
    
    
private boolean pleaseStop; 
// private volatile boolean pleaseStop
//Because of volatile while loop cannot cache  
// Re-checks pleaseStop every iteration
public void run() {
    
    
    // While loop caches pleaseStop variable 
    //This loop will never end
    while (!pleaseStop)  {
    
     // do some stuff... } }
public void tellMeToStop()
    {
    
     pleaseStop = true; } }

4.4 When not to use volatile

  1. Fields that declared final (never change)
  2. Variables that are accessed by only one thread
  3. Complex operations (Even things like x=x+5)

4.5 On another point: Thread.yield() may be better than Thread.sleep()

  1. yield stops the thread running continuously and gives some time back to the Operating System.
  2. yield just gives up the thread’s turn, and regains it in
    the next round.
  3. sleep() has a slightly larger overhead because it creates a system that includes some kind of timer that will wake the process. (Depends on implementation basically)
    Hence yield sometimes better

Homework

  1. Create several different threads
    1. One that constantly loops printing out hello
    2. One that loops printing out hello with a 1 second sleep in between
  2. Interrupt the threads and see what happens!
  3. Add interrupt support into them so that you can stop them looping
    with an interrupt
  4. Create a shared variable pleaseFinish to terminate the thread
    1. Try both with and without volatile…

猜你喜欢

转载自blog.csdn.net/GreatSimulation/article/details/108818590