zoukankan      html  css  js  c++  java
  • Java技术之如何保证同一资源被多个线程并发访问时的完整性?

    常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。Java语言在多线程编程上实现了完全对象化,提供了对同步机制的良好支持。

    在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。管道方法不建议使用,阻塞队列方法在之前已有描述,现只提供前两种实现方法。

    - wait()/notify()方法

    - await()/signal()方法

    - BlockingQueue阻塞队列方法

    - PipedInputStream/PipedOutputStream

    一、生产者类:

    ```

    public class Producer extends Thread { // 每次生产的产品数量

    private int num;

    // 所在放置的仓库

    private Storage storage;

    // 构造函数,设置仓库

    public Producer(Storage storage) {

    this.storage = storage;

    }

    // 线程run函数

    public void run() {

    produce(num);

    }

    // 调用仓库Storage的生产函数

    public void produce(int num) {

    storage.produce(num);

    }

    public int getNum() {

    return num;

    }

    public void setNum(int num) {

    this.num = num;

    }

    public Storage getStorage() {

    return storage;

    }

    public void setStorage(Storage storage) {

    this.storage = storage;

    }

    }

    ```

    二、消费者类:

    ```

    public class Consumer extends Thread { // 每次消费的产品数量

    private int num;

    // 所在放置的仓库

    private Storage storage;

    // 构造函数,设置仓库

    public Consumer(Storage storage) {

    this.storage = storage;

    }

    // 线程run函数

    public void run() {

    consume(num);

    }

    // 调用仓库Storage的生产函数

    public void consume(int num) {

    storage.consume(num);

    }

    // get/set方法

    public int getNum() {

    return num;

    }

    public void setNum(int num) {

    this.num = num;

    }

    public Storage getStorage() {

    return storage;

    }

    public void setStorage(Storage storage) {

    this.storage = storage;

    }

    }

    ```

    仓库类:(wait()/notify()方法)

    ```

    public class Storage { // 仓库最大存储量

    private final int MAX_SIZE = 100;

    // 仓库存储的载体

    private LinkedList<Object> list = new LinkedList<Object>();

    // 生产num个产品

    public void produce(int num) {

    // 同步代码段

    synchronized (list) {

    // 如果仓库剩余容量不足

    while (list.size() + num > MAX_SIZE) {

    System.out.print("【要生产的产品数量】:" + num);

    System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!");

    try {

    list.wait();// 由于条件不满足,生产阻塞

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    // 生产条件满足情况下,生产num个产品

    for (int i = 1; i <= num; ++i) {

    list.add(new Object());

    }

    System.out.print("【已经生产产品数】:" + num);

    System.out.println(" 【现仓储量为】:" + list.size());

    list.notifyAll();

    }

    }

    // 消费num个产品

    public void consume(int num) {

    // 同步代码段

    synchronized (list) {

    // 如果仓库存储量不足

    while (list.size() < num) {

    System.out.print("【要消费的产品数量】:" + num);

    System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!");

    try {

    // 由于条件不满足,消费阻塞

    list.wait();

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    // 消费条件满足情况下,消费num个产品

    for (int i = 1; i <= num; ++i) {

    list.remove();

    }

    System.out.print("【已经消费产品数】:" + num);

    System.out.println(" 【现仓储)量为】:" + list.size());

    list.notifyAll();

    }

    }

    // get/set方法

    public LinkedList<Object> getList() {

    return list;

    }

    public void setList(LinkedList<Object> list) {

    this.list = list;

    }

    public int getMAX_SIZE() {

    return MAX_SIZE;

    }

    }

    ```

    仓库类:(await()/signal()方法)

    ```

    public class Storage { // 仓库最大存储量

    // 仓库最大存储量

    private final int MAX_SIZE = 100;

    // 仓库存储的载体

    private LinkedList<Object> list = new LinkedList<Object>();

    // 锁

    private final Lock lock = new ReentrantLock();

    // 仓库满的条件变量

    private final Condition full = lock.newCondition();

    // 仓库空的条件变量

    private final Condition empty = lock.newCondition();

    // 生产num个产品

    public void produce(int num) {

    // 获得锁

    lock.lock();

    // 如果仓库剩余容量不足

    while (list.size() + num > MAX_SIZE) {

    System.out.print("【要生产的产品数量】:" + num);

    System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!");

    try {

    // 由于条件不满足,生产阻塞

    full.await();

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    // 生产条件满足情况下,生产num个产品

    for (int i = 1; i <= num; ++i) {

    list.add(new Object());

    }

    System.out.print("【已经生产产品数】:" + num);

    System.out.println(" 【现仓储量为】:" + list.size());

    // 唤醒其他所有线程

    full.signalAll();

    empty.signalAll();

    // 释放锁

    lock.unlock();

    }

    // 消费num个产品

    public void consume(int num) {

    // 获得锁

    lock.lock();

    // 如果仓库存储量不足

    while (list.size() < num) {

    System.out.print("【要消费的产品数量】:" + num);

    System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!");

    try {

    // 由于条件不满足,消费阻塞

    empty.await();

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    // 消费条件满足情况下,消费num个产品

    for (int i = 1; i <= num; ++i) {

    list.remove();

    }

    System.out.print("【已经消费产品数】:" + num);

    System.out.println(" 【现仓储)量为】:" + list.size());

    // 唤醒其他所有线程

    full.signalAll();

    empty.signalAll();

    // 释放锁

    lock.unlock();

    }

    // set/get方法

    public int getMAX_SIZE() {

    return MAX_SIZE;

    }

    public LinkedList<Object> getList() {

    return list;

    }

    public void setList(LinkedList<Object> list) {

    this.list = list;

    }

    }

  • 相关阅读:
    关于软工文档规范性——国标文档
    关于游戏平衡性——王者荣耀野怪数值参考
    单元测试特性标签(结合代码)
    常用标签梳理
    图片文件的转换、加载及缩放显示
    认识ManualResetEvent
    HTML简介
    HTML基本结构
    15年,我在深圳
    为什么坚持,想一想当初
  • 原文地址:https://www.cnblogs.com/CQqf/p/10790281.html
Copyright © 2011-2022 走看看