当前位置:网站首页>JUC - thread interrupt and thread waiting and wakeup (locksupport)

JUC - thread interrupt and thread waiting and wakeup (locksupport)

2022-06-22 04:40:00 It takes time for fish to find water

Interrupt mechanism

What is interrupt mechanism ?

First
​ A thread should not be forced to interrupt or stop by other threads , It is A thread should stop itself , Decide your own destiny .
​ therefore ,Thread.stop, Thead.suspend, Thead.resumer It's been abandoned .

secondly
​ stay Java There is no way to stop a thread immediately , However, stopping threads is particularly important , For example, cancel a time-consuming operation .
​ therefore ,Java Provides a negotiation mechanism for stopping threads – interrupt , I.e. interrupt identification negotiation mechanism .

Interruption is just a mechanism for negotiation and cooperation ,Java There is no syntax added to interrupts in , The interruption process needs to be implemented by the programmer himself .

To interrupt a thread , You need to manually call the thread's interrupt Method , This method only sets the interrupt representation of the thread object to true
Then you need to write your own code to constantly detect the identification bit of the current thread , If true, Indicates that another thread requests this thread to interrupt

Each thread object has an interrupt identifier bit , Used to indicate whether a thread is interrupted ; The identification bit is true To interrupt , by false Means not interrupted ;
By calling the interrupt Method sets the identity of the thread to true; Can be invoked in other threads , You can also call it in your own thread .

 Insert picture description here

  1. adopt volatile Variable implementation
  2. adopt AtomicBoolean Realization
  3. adopt Thread Class has its own interrupt api Example method implementation
 public static void main(String[] args)
    {
    
        Thread t1 = new Thread(() -> {
    
            while (true)
            {
    
                if(Thread.currentThread().isInterrupted())
                {
    
                    System.out.println(Thread.currentThread().getName()+"\t isInterrupted() Changed to true, The program to stop ");
                    break;
                }
                System.out.println("t1 -----hello interrupt api");
            }
        }, "t1");
        t1.start();

        System.out.println("-----t1 The default interrupt flag bit of :"+t1.isInterrupted());

        // Pause for milliseconds 
        try {
     TimeUnit.MILLISECONDS.sleep(20); } catch (InterruptedException e) {
     e.printStackTrace(); }

        //t2 towards t1 Issue negotiation , take t1 The interrupt flag bit of is set to true hope t1 stop 
        new Thread(() -> {
    
            t1.interrupt();
        },"t2").start();
        //t1.interrupt();

    }

 static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
    private static void m2_atomicBoolean()
    {
    
        new Thread(() -> {
    
            while (true)
            {
    
                if(atomicBoolean.get())
                {
    
                    System.out.println(Thread.currentThread().getName()+"\t atomicBoolean Changed to true, The program to stop ");
                    break;
                }
                System.out.println("t1 -----hello atomicBoolean");
            }
        },"t1").start();

        // Pause for milliseconds 
        try {
     TimeUnit.MILLISECONDS.sleep(20); } catch (InterruptedException e) {
     e.printStackTrace(); }

        new Thread(() -> {
    
            atomicBoolean.set(true);
        },"t2").start();
    }

static volatile boolean isStop = false;
    private static void m1_volatile()
    {
    
        new Thread(() -> {
    
            while (true)
            {
    
                if(isStop)
                {
    
                    System.out.println(Thread.currentThread().getName()+"\t isStop Changed to true, The program to stop ");
                    break;
                }
                System.out.println("t1 -----hello volatile");
            }
        },"t1").start();

        // Pause for milliseconds 
        try {
     TimeUnit.MILLISECONDS.sleep(20); } catch (InterruptedException e) {
     e.printStackTrace(); }

        new Thread(() -> {
    
            isStop = true;
        },"t2").start();
    }

summary : When it comes to a thread , call interrupt When the method is used :
① If the thread is in Normal active state , The thread's interrupt flag will be set to true, That's it .
The thread with interrupt flag will continue to run normally , Unaffected .
therefore ,interrupt() It doesn't really interrupt threads , You need to cooperate with the called thread .

② If the thread is blocked ( For example, dealing with sleep、wait、join Equal state ), To call the current thread object in another thread interrupt Method , Then the thread will immediately exit the blocked state , And throw a interruptedException abnormal .

  public static void main(String[] args)
    {
    
        // Example method interrupt() Just set the interrupt status bit of the thread to true, Thread will not be stopped 
        Thread t1 = new Thread(() -> {
    
            for (int i = 1; i <=300; i++)
            {
    
                System.out.println("-----: "+i);
            }
            System.out.println("t1 Thread calls interrupt() The interrupt identifier of the following 02:"+Thread.currentThread().isInterrupted());
        }, "t1");
        t1.start();

        System.out.println("t1 Thread default interrupt identifier :"+t1.isInterrupted());//false

        // Pause for milliseconds 
        try {
     TimeUnit.MILLISECONDS.sleep(2); } catch (InterruptedException e) {
     e.printStackTrace(); }
        t1.interrupt();//true
        System.out.println("t1 Thread calls interrupt() The interrupt identifier of the following 01:"+t1.isInterrupted());//true

        try {
     TimeUnit.MILLISECONDS.sleep(2000); } catch (InterruptedException e) {
     e.printStackTrace(); }
        System.out.println("t1 Thread calls interrupt() The interrupt identifier of the following 03:"+t1.isInterrupted());
        //????---false Interrupting an inactive thread does not have any effect .
        //ps:  Two seconds later, the thread has finished executing 
    }

In depth analysis of interrupted negotiation cases

 public static void main(String[] args)
    {
    
        Thread t1 = new Thread(() -> {
    
            while (true)
            {
    
                if(Thread.currentThread().isInterrupted())
                {
    
                    System.out.println(Thread.currentThread().getName()+"\t " +
                            " Interrupt flag bit :"+Thread.currentThread().isInterrupted()+"  The program to stop ");
                    break;
                }

                try {
    
                    Thread.sleep(200);
                } catch (InterruptedException e) {
    
                   // Thread.currentThread().interrupt();// Without it , The program will not stop , Why in the exception , Call again ??
                    e.printStackTrace();
                }

                System.out.println("-----hello InterruptDemo3");
            }
        }, "t1");
        t1.start();

        // Pause the thread for a few seconds 
        try {
     TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
     e.printStackTrace(); }

        new Thread(() -> t1.interrupt(),"t2").start();
    }

/** * 1  Interrupt flag bit , Default false * 2 t2 ----> t1 An interrupt negotiation was issued ,t2 call t1.interrupt(), Interrupt flag bit true * 3  Interrupt flag bit true, Normal condition , The program to stop ,^_^ * 4  Interrupt flag bit true, Abnormal situation ,InterruptedException, The interrupt status will be cleared , And will receive InterruptedException . Interrupt flag bit false *  Cause infinite loop  * * 5  stay catch In block , The interrupt flag bit needs to be set to again true,2 Call to stop the program OK */

Official description

 Insert picture description here

Interruption is just a negotiation mechanism , Modifying the interrupt flag bit is nothing more , Not immediately stop interrupt

  public static void main(String[] args)
    {
    
        // Test whether the current thread is interrupted ( Check interrupt flag ), Return to one boolean And clear the interrupt state ,
        //  The interrupt state has been cleared on the second call , Will return a false.


        System.out.println(Thread.currentThread().getName()+"\t"+Thread.interrupted()); //false
        System.out.println(Thread.currentThread().getName()+"\t"+Thread.interrupted());//false
        System.out.println("----1");
        Thread.currentThread().interrupt();//  The interrupt flag bit is set to true
        System.out.println("----2");
        System.out.println(Thread.currentThread().getName()+"\t"+Thread.interrupted());//true
        System.out.println(Thread.currentThread().getName()+"\t"+Thread.interrupted());//false

        LockSupport.park();

        Thread.interrupted();// Static methods 

        Thread.currentThread().isInterrupted();// Example method 
    }

Static methods interrupted The interrupt status will be clear ( From the source code ClearInterrupted by true)

Example method isInterrupted Will not be ( Incoming parameter ClearInterrupted by false)

summary

Thread interrupt related methods :

public void interrupt(); interrupt() A method is an instance method
It notifies the target thread of an interrupt , Only set the interrupt flag bit of the target thread to true.

public boolean isInterrupted(); isInterrupted() Method is also an instance method
It determines whether the current thread is interrupted ( Check the interrupt flag bit ) And get the interrupt flag

public static boolean interrupted(), Thread Class static methods interrupted()
Returns the true value of the interrupt status of the current thread (boolean type ) After that, the interrupt status of the current thread will be set to false, After this method is called, the status of the interrupt flag bit of the current thread will be cleared ( Place the interrupt flag at false 了 ), Returns the current value and resets it to zero false

Thread wait and wake

LockSupport Is a basic thread blocking primitive used to create synchronization classes with other classes

file

 Insert picture description here

LockSupport Medium park() and unpark() The functions of are to block threads and to unblock blocked threads

There are three ways for threads to wait for wakeup

  1. Use Object Of wait() Method to make the thread wait , Use Object Medium notify() Method wake up thread
  2. Use JUC In bag Condition Of await Method to make the thread wait , Use signal() Method wake up thread
  3. LockSupport Class can block the current thread and wake up the specified blocked thread

Object

 private static void syncWaitNotify()
    {
    
        Object objectLock = new Object();

        new Thread(() -> {
    
            try {
     TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
     e.printStackTrace(); }
            synchronized (objectLock){
    
                System.out.println(Thread.currentThread().getName()+"\t ----come in");
                try {
    
                    objectLock.wait();
                } catch (InterruptedException e) {
    
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"\t ---- Awakened ");
            }
        },"t1").start();

        // Pause the thread for a few seconds 
        try {
     TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
     e.printStackTrace(); }

        new Thread(() -> {
    
            synchronized (objectLock){
    
                objectLock.notify();
                System.out.println(Thread.currentThread().getName()+"\t ---- A notice ");
            }
        },"t2").start();
    }

wait() and notify() Must be placed in a synchronized code block or synchronized method , And appear in pairs
Must be present wait() stay notify(), Otherwise, the program cannot be executed , Can't wake up


Condition

 private static void lockAwaitSignal()
    {
    
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();

        new Thread(() -> {
    
            try {
     TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
     e.printStackTrace(); }
            lock.lock();
            try
            {
    
                System.out.println(Thread.currentThread().getName()+"\t ----come in");
                condition.await();
                System.out.println(Thread.currentThread().getName()+"\t ---- Awakened ");
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            } finally {
    
                lock.unlock();
            }
        },"t1").start();

        // Pause the thread for a few seconds 
        try {
     TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
     e.printStackTrace(); }

        new Thread(() -> {
    
            lock.lock();
            try
            {
    
                condition.signal();
                System.out.println(Thread.currentThread().getName()+"\t ---- A notice ");
            }finally {
    
                lock.unlock();
            }
        },"t2").start();
    }

Condtion Thread waiting and wakeup methods in , You need to acquire the lock first
Be sure to await Again signal


LockSupport

LockSupport Class uses a method called Permit( The license ) To achieve Blocking and waking threads The function of , Each thread has a license (permit)
But with Semaphores Different , Licenses do not accumulate , At most one

park()/park(Object blocker): Blocking ,permit The license has no default direction , So at the beginning of the call park() Method will block the current thread , Until the current thread is issued by another thread permit,park The method will be awakened

unpark(Thread thread): Wake up the , call unpark(thread) After the method , Will be thread License for threads permit issue , Will wake up automatically park Threads , That is, in the previous blocking LockSupport.park() Method will immediately return

 public static void main(String[] args)
    {
    
        Thread t1 = new Thread(() -> {
    
            try {
     TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) {
     e.printStackTrace(); }
            System.out.println(Thread.currentThread().getName() + "\t ----come in"+System.currentTimeMillis());
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + "\t ---- Awakened "+System.currentTimeMillis());
        }, "t1");
        t1.start();

        // Pause the thread for a few seconds 
        //try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }

        new Thread(() -> {
    
            LockSupport.unpark(t1);
            System.out.println(Thread.currentThread().getName()+"\t ---- A notice ");
        },"t2").start();

    }

LockSupport There are no lock block requirements
The previous error wakes up first and then waits ,LockSupport Still support , First unpark Again park It is equivalent to having a pass in advance unpark,park There is no interception .park and unpark Must correspond to each other , because Licenses do not accumulate , At most one

summary

LockSupport Is a thread blocking tool class , All methods are static , The thread can be blocked at any location , After blocking, there is also a wake-up method for . in the final analysis ,LockSupport Called Unsafe Medium native Code (native The identified method calls the underlying C++、C Code ).

LockSupport Provided park() and unpark() Method to implement the process of blocking and unblocking threads
LockSupport And every thread that uses it has a license (permit) relation .
Each thread has an associated permit,permit At most one , Repeated calls to unpark It will not accumulate vouchers .

understand

Thread blocking requires consuming credentials (permit), There is only one voucher at most .

When calling park When the method is used

  • If there is a certificate , It will consume the voucher directly and exit normally ;
  • If there is no certificate , You have to block and wait for credentials to be available ;

and unpark On the contrary , It will add a voucher , But there can only be one voucher at most , Accumulation is invalid .

Why can we break through wait/notify The original calling sequence of ?

because unpark Got a certificate , Call later park Method , You can honestly rely on vouchers for consumption , So it won't block .
After the vouchers are issued first, they can be unblocked later .

Why wake up twice and block twice , But the end result will still block the thread ?

Because the maximum number of vouchers is 1, Two consecutive calls unpark And call once unpark The effect is the same , Only one voucher will be added ;
And call twice park But you need to consume two vouchers , If the certificate is not enough, it cannot be released .

原网站

版权声明
本文为[It takes time for fish to find water]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206220435168405.html