美文网首页java基础
Java锁(1)ReentrantLock

Java锁(1)ReentrantLock

作者: 菜鸟上路咯 | 来源:发表于2019-03-13 18:02 被阅读0次

锁使用的是ReentrantLock,为一种可重入的互斥锁
...
package com.zc.lock;

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

class Dept {
private int max; // 仓库大小
private int has; // 仓库已用大小
private Lock lock; // 锁
private Condition fullcondition; // 生产通知 控制生产线程
private Condition emptycondition; // 消费通知 控制消费线程

// 创建仓库
public Dept(int max) {
    this.max = max;
    this.has = 0;
    this.lock = new ReentrantLock();
    this.emptycondition = lock.newCondition();
    this.fullcondition = lock.newCondition();
}

// 装入
public void put(int num) {
    lock.lock();
    int wanPuttNum = num; // 想要装入的数量
    try {
        while (wanPuttNum > 0) {
            while (has == max) {
                fullcondition.await(); // 仓库容量不足时,生产线程等待
                System.out.println("Producers ---wait---wantput" + wanPuttNum);
            }
            int couldPutNum = (wanPuttNum + has > max) ? max - has : wanPuttNum; // 本次装入的数量
            int endhas = has + couldPutNum; // 操作后的仓库已用容量
            System.out.println(Thread.currentThread().getName() + "--wantput--" + wanPuttNum + "--couldput--" + couldPutNum + "--操作前--"
                    + has + "--操作后--" + endhas);
            wanPuttNum = wanPuttNum - couldPutNum; // 判断是否还要2次装入
            has = endhas; // 修改已用容量
            emptycondition.signalAll();
        }
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        lock.unlock(); // 解锁操作需要放入finally,避免出现死锁
    }
}

public void get(int num) {
    lock.lock();
    int wantGetNum = num; // 期望获取的数量
    try {
        while (wantGetNum > 0) {
            while (has == 0) {
                emptycondition.await();
                System.out.println("Customers ---wait--wantget" + wantGetNum);
            }
            int couldGetNum = (wantGetNum > has) ? has : wantGetNum; // 本次获取的数量
            int endhas = has - couldGetNum; // 操作结束的已用容量
            System.out.println(Thread.currentThread().getName() + "--想要获得--" + wantGetNum + "--本次获得--" + couldGetNum + "--操作前--" + has
                    + "--操作后--" + endhas);
            wantGetNum = wantGetNum - couldGetNum; // 判断是否需要再次请求
            has = endhas; // 更新已用容量
            fullcondition.signalAll(); // 通知生产线程
        }
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

}

//生产者
class Producers {
private Dept dept;

public Producers(Dept dept) {
    this.dept = dept;
}

public void doPut(final int num) {
    new Thread() {
        public void run() {
            dept.put(num);
        }
    }.start();

}

}

class Customers {
private Dept dept;

public Customers(Dept dept) {
    this.dept = dept;
}

public void doGet(final int num) {
    new Thread() {
        public void run() {
            dept.get(num);
        }
    }.start();
}

}

public class Test02 {

public static void main(String[] args) {
    Dept dept = new Dept(200);
    Customers ce = new Customers(dept);
    Producers pe = new Producers(dept);

    pe.doPut(90);
    ce.doGet(210);
    pe.doPut(150);
    ce.doGet(30);
}

}

...

结果为: 结果.png

感觉condition.await就相当于object.wait,condition.signal则是object.notify。condition灵活性更好,能够完成更细精度的通知

相关文章

网友评论

    本文标题:Java锁(1)ReentrantLock

    本文链接:https://www.haomeiwen.com/subject/tcitmqtx.html