JAVA多线程-Lock类API

Lock的api的用法:

我们先看下lock接口中有哪些方法:

public interface Lock {

    /**

     * 获取锁,如果获取不到就一直等待,与synchronized一样
      */

    void lock();


    /**
    * 该方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁,
    * 则这个线程能够响应中断,
    * 即中断线程的等待状态。也就是说,
    * 当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,
    * 假若此时线程A获取到了锁,而线程B只有在等待,
    * 那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。
    */

    void lockInterruptibly() throws InterruptedException;

    /**
     * 该方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,
     * 如果获取失败(即锁已被其他线程获取),则返回false,
     * 也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。     
    */

    boolean tryLock();



    /**

     * 该方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,
     * 在时间期限之内如果还拿不到锁,就返回false。
     * 如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true  
    */

    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;



    /**

     * 释放锁

     */

    void unlock();



    /**
     *
     * Condition是Java提供了来实现等待/通知的类,
     * Condition类还提供比wait/notify更丰富的功能,
     * Condition对象是由lock对象所创建的。但是同一个锁可以创建多个Condition的对象,
     * 即创建多个对象监视器。这样的好处就是可以指定唤醒线程。
     * notify唤醒的线程是随机唤醒一个 ,具体得会在后面线程间得通信讲    */

    Condition newCondition();

}

ReentrantLock,意思是“可重入锁”,关于可重入锁,我们在前面synchronized中已经提到过,ReentrantLock简单得用法我们前面一篇也简单得用到过。ReentrantLock是实现了Lock接口的类,并且ReentrantLock提供了更多的方法,我们先看下ReentrantLock类继承关系:

public class ReentrantLock implements Lock, java.io.Serializable

我们可以看到实现了lock,和序列化接口。

那么就先使用下lock得api.

Lock()和unlock()我们上一章已经用到过,下面我们讲另外得方法:

tryLock()用法:

public class Account {

    private Lock lock = new ReentrantLock();

    public   void add(BigDecimal amount , String name) {

        //尝试获取锁,获取不到,直接跳出

        if(lock.tryLock()) {

            System.out.println(" 开始充值,线程名: " + Thread.currentThread().getName());

            try {

                Thread.sleep(2000);

                System.out.println(" 结束充值,线程名: " + Thread.currentThread().getName());

            } catch (InterruptedException e) {

                e.printStackTrace();

            }finally {

                lock.unlock();

            }

        }else {

            System.out.println("获取锁失败,不进行充值,线程名: " + Thread.currentThread().getName());

        }

    }

}

然后继续充值线程类:


public class CzThread extends Thread{


    private Account account;


    private String accountName;

  
    public CzThread(Account account) {

        this.account = account;

    }

   

    @Override

    public void run() {

        account.add(new BigDecimal("100"), accountName);

    }


    public Account getAccount() {

        return account;

    }


    public void setAccount(Account account) {

        this.account = account;

    }


    public String getAccountName() {

        return accountName;

    }


    public void setAccountName(String accountName) {

        this.accountName = accountName;

    }


}

主线程类:

public class MainThread {

    public static void main(String[] args) throws InterruptedException {

        Account account = new Account();

       

        CzThread cz1 = new CzThread(account);

        cz1.setName("thread1");

        cz1.start();

       

        CzThread cz2 = new CzThread(account);

        cz2.setName("thread2");

        cz2.start();

    }

}

 

执行结果:

获取锁失败,不进行充值,线程名: thread2

 开始充值,线程名: thread1

 结束充值,线程名: thread1

 

我们继续看下tryLock(long time, TimeUnit unit)用法,稍微修改下Account类:

public class Account {

    private Lock lock = new ReentrantLock();

    public   void add(BigDecimal amount , String name) throws InterruptedException {

        /***

         * 等待了5s后

         */

        if(lock.tryLock(5, TimeUnit.SECONDS)) {

            System.out.println(" 开始充值,线程名: " + Thread.currentThread().getName());

            try {

                Thread.sleep(2000);

                System.out.println(" 结束充值,线程名: " + Thread.currentThread().getName());

            } catch (InterruptedException e) {

                e.printStackTrace();

            }finally {

                lock.unlock();

            }

        }else {

            System.out.println("获取锁失败,不进行充值,线程名: " + Thread.currentThread().getName());

        }

    }
   

}

 

充值类也要修改下,因为需要抛异常:

public class CzThread extends Thread{

    private Account account;

    private String accountName;
   

    public CzThread(Account account) {

        this.account = account;

    }

   
    @Override

    public void run() {

        try {

            account.add(new BigDecimal("100"), accountName);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

    public Account getAccount() {

        return account;

    }

    public void setAccount(Account account) {

        this.account = account;

    }


    public String getAccountName() {

        return accountName;

    }


    public void setAccountName(String accountName) {

        this.accountName = accountName;

    }
}

看下执行结果:

开始充值,线程名: thread2

 结束充值,线程名: thread2

 开始充值,线程名: thread1

 结束充值,线程名: thread1

 

我们看到线程1和2都执行完了,因为等待了5s得锁,所以会执行。

lockInterruptibly与Condition,我们会在后面得线程通信讲,下一篇我们会解析,我们上面讲的得方法得原理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值