011.多线程-lock锁

版权声明:本文为博主原创文章,允许转载,请标明出处。

类似于上一篇使用synchronized实现生产者与消费者间的通信, 这里使用lock锁来实现。

package cn.qbz.thread;

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

/**
 * @Author: 花生米
 * @Date: 2018/11/15 22:04
 */
public class LockTest {

    public static void main(String[] args) {
        Student student = new Student();
        Lock lock = new ReentrantLock();
        Condition produceCondition = lock.newCondition();
        Condition consumerCondition = lock.newCondition();

        ProduceTest produceTest = new ProduceTest(student, lock, produceCondition, consumerCondition);
        ConsumerTest consumerTest = new ConsumerTest(student, lock, produceCondition, consumerCondition);

        produceTest.start();
        consumerTest.start();
    }
}

class ProduceTest extends Thread {
    private Student student;
    private Lock lock;
    private Condition produceCondition;
    private Condition consumerCondition;

    public ProduceTest(Student student, Lock lock,
                       Condition produceCondition,
                       Condition consumerCondition) {
        this.student = student;
        this.lock = lock;
        this.produceCondition = produceCondition;
        this.consumerCondition = consumerCondition;
    }

    @Override
    public void run() {
        int num = 1;
        while (true) {
            lock.lock();
            try {
                //如果可以生产,生产者生产
                if (student.getCanProduce()) {
                    if (num == 1) {
                        student.setAge(6);
                        student.setName("小王");
                        num = 0;
                    } else {
                        student.setName("老王");
                        student.setAge(99);
                        num = 1;
                    }

                    //重置生产者不可以生产
                    student.setCanProduce(false);
                }

                consumerCondition.signalAll();

                produceCondition.await();

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }
    }
}

class ConsumerTest extends Thread {
    private Student student;
    private Lock lock;
    private Condition produceCondition;
    private Condition consumerCondition;

    public ConsumerTest(Student student, Lock lock, Condition produceCondition, Condition consumerCondition) {
        this.student = student;
        this.lock = lock;
        this.produceCondition = produceCondition;
        this.consumerCondition = consumerCondition;
    }

    @Override
    public void run() {
        while (true) {
            lock.lock();
            try {
                //如果不可以生产,进行消费
                if (!student.getCanProduce()) {
                    //重置生产者可以生产
                    student.setCanProduce(true);
                    System.out.println(student.toString());
                }

                produceCondition.signalAll();
                consumerCondition.await();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }
    }
}

class Student {
    private String name;
    private Integer age;
    private Boolean canProduce = true;

    public Boolean getCanProduce() {
        return canProduce;
    }

    public void setCanProduce(Boolean canProduce) {
        this.canProduce = canProduce;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

lock中常用方法:

lock()、unlock()

	Lock lock = new ReentrantLock();
	lock.lock();
	try{
	//可能会出现线程安全的操作
	}finally{
	//一定在finally中释放锁
	//也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常
	  lock.unlock();
	}

await()、signal()、signalAll()

	Lock lock = new ReentrantLock();
	Condition produceCondition = lock.newCondition();
	Condition consumerCondition = lock.newCondition();

	consumerCondition.signalAll();
	produceCondition.await();

lock中的await方法类似于synchronized的wait, signal、signalAll类似于notify、notifyAll。

需要注意: 虽然多个线程使用同一把lock锁, 但是每个线程的condition都是唯一的, 使用时需要注意。


trylock() 其功能与 lock() 一样,不过会有返回值, true:获取到lock锁;false:未获取lock锁。

   if (lock.tryLock()) {
        try {
            //如果不可以生产,进行消费
            if (!student.getCanProduce()) {
                //重置生产者可以生产
                student.setCanProduce(true);
                System.out.println(student.toString());
            }

            produceCondition.signalAll();
            consumerCondition.await();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

tryLock(long time, TimeUnit unit) 与tryLock()类似, 只不过在未获取到锁时,设置了一个等待时间来尝试再次拿锁。


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java达人

数据字典项实现方案

在应用开发中,总会遇到许多数据字典项,比如对象状态、对象类型等等,这些项一般都是固定的若干可选值选项,比如对象状态可能有新建、修改、删除等状态,这些数据字典项一...

1K7
来自专栏Android相关

X86 Assemble指令--MOVS指令簇

该指令簇包括: MOVS mem16,mem16:显式指定源操作数与目的操作数 MOVSB:每次移动一个字节 MOVSW:每次移动一个字 MOVSD:每...

1462
来自专栏java 成神之路

阻塞队列和ArrayBlockingQueue源码解析(JDK1.8)

2946
来自专栏微信公众号:Java团长

Java基础知识详细总结

ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类...

1383
来自专栏熊二哥

快速入门系列--CLR--03泛型集合

.NET中的泛型集合 在这里主要介绍常见的泛型集合,很多时候其并发时的线程安全性常常令我们担忧。因而简述下.NET并发时线程安全特性,其详情请见MSDN。 ...

1777
来自专栏大内老A

关于CLR内存管理一些深层次的讨论[上篇]

半年之前,PM让我在部门内部进行一次关于“内存泄露”的专题分享,我为此准备了一份PPT。今天无意中将其翻出来,觉得里面提到的关于CLR下关于内存管理部分的内存还...

2008
来自专栏博岩Java大讲堂

Java集合--线程安全(CopyOnWrite机制)

3274
来自专栏微信公众号:Java团长

Java面试题整理及参考答案

允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用).主要有以下优点:

1172
来自专栏你不就像风一样

Java多线程核心技术(四)Lock的使用

在Java多线程中,可以使用 synchronized 关键字来实现线程之间同步互斥,但在JDK1.5中新增加了 ReentrantLock 类也能达到同样的效...

1213
来自专栏全华班

java学习手册-JAVA程序员笔试题(一)

JAVA程序员笔试题(一) 一、选择题: 1、类的成员变量要求仅仅能够被同一package下的类访问,应该使用哪个修辞词 A. Protected、B. Pub...

4035

扫码关注云+社区

领取腾讯云代金券