Java多线程:lockInterruptibly()方法

1,469 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

Java多线程:lockInterruptibly()方法

lockInterruptibly() 方法的作用:如果当前线程未被中断则获得锁,如果当前线程被中断则出现异常。

package com.wkcto.lock.reentrant;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * lockInterruptibly() 方法的作用:如果当前线程未被中断则获得锁,如果当前线程被中断则出现异常.
 */
public class Test05 {
    static class Servier{
        private Lock lock = new ReentrantLock();        //定义锁对象
        public void serviceMethod(){
            try {
//                lock.lock();        //获得锁定,即使调用了线程的interrupt()方法,也没有真正的中断线程
                lock.lockInterruptibly();   //如果线程被中断了,不会获得锁,会产生异常
                System.out.println(Thread.currentThread().getName() + "-- begin lock");
                //执行一段耗时的操作
                for (int i = 0; i < Integer.MAX_VALUE; i++) {
                    new StringBuilder();
                }
                System.out.println( Thread.currentThread().getName() + " -- end lock");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println( Thread.currentThread().getName() + " ***** 释放锁");
                lock.unlock();      //释放锁
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Servier  s = new Servier();
        Runnable r = new Runnable() {
            @Override
            public void run() {
                s.serviceMethod();
            }
        };
        Thread t1 = new Thread(r);
        t1.start();

        Thread.sleep(50);
        Thread t2 = new Thread(r);
        t2.start();
        Thread.sleep(50);
        t2.interrupt();     //中断t2线程
    }
}

对于synchronized内部锁来说,如果一个线程在等待锁,只有两个结果:要么该线程获得锁继续执行;要么就保持等待。

对于ReentrantLock可重入锁来说,提供另外一种可能,在等待锁的过程中,程序可以根据需要取消对锁的请求。

package com.wkcto.lock.reentrant;

import com.wkcto.pipestream.Test2;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 *  通过ReentrantLock锁的lockInterruptibly()方法避免死锁的产生
 */
public class Test06 {
    static  class  IntLock implements Runnable{
        //创建两个ReentrantLock 锁对象
        public static ReentrantLock lock1 = new ReentrantLock();
        public static ReentrantLock lock2 = new ReentrantLock();
        int lockNum;        //定义整数变量,决定使用哪个锁

        public IntLock(int lockNum) {
            this.lockNum = lockNum;
        }

        @Override
        public void run() {
            try {
                if ( lockNum % 2 == 1){         //奇数,先锁1,再锁2
                    lock1.lockInterruptibly();
                    System.out.println(Thread.currentThread().getName() + "获得锁1,还需要获得锁2");
                    Thread.sleep(new Random().nextInt(500));
                    lock2.lockInterruptibly();
                    System.out.println(Thread.currentThread().getName() + "同时获得了锁1与锁2....");
                }else {     //偶数,先锁2,再锁1
                    lock2.lockInterruptibly();
                    System.out.println(Thread.currentThread().getName() + "获得锁2,还需要获得锁1");
                    Thread.sleep(new Random().nextInt(500));
                    lock1.lockInterruptibly();
                    System.out.println(Thread.currentThread().getName() + "同时获得了锁1与锁2....");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if ( lock1.isHeldByCurrentThread())         //判断当前线程是否持有该锁
                    lock1.unlock();
                if (lock2.isHeldByCurrentThread())
                    lock2.unlock();
                System.out.println( Thread.currentThread().getName() + "线程退出");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        IntLock intLock1 = new IntLock(11);
        IntLock intLock2  = new IntLock(22);

        Thread t1 = new Thread(intLock1);
        Thread t2 = new Thread(intLock2);
        t1.start();
        t2.start();

        //在main线程,等待3000秒,如果还有线程没有结束就中断该线程
        Thread.sleep(3000);

        //可以中断任何一个线程来解决死锁, t2线程会放弃对锁1的申请,同时释放锁2,  t1线程会完成它的任务
        if (t2.isAlive()){ t2.interrupt();}
    }
}