好程序员-千锋教育旗下高端IT职业教育品牌

400-811-9990
我的账户
好程序员

专注高端IT职业培训

亲爱的猿猿,欢迎!

已有账号,请

如尚未注册?

  • 客服QQ
  • 官方微信

    好程序员

    专注高端IT职业培训

[BigData] 好程序员面试题分享同一资源多线程并发访问时的完整性

[复制链接]
63 0
叶子老师 发表于 6 天前 | 只看该作者 |阅读模式 打印 上一主题 下一主题
  好程序员面试题分享同一资源多线程并发访问时的完整性常用的同步方法是采用信号或加锁机制,确保资源在任意时刻至多被一个线程访问。Java语言在多线程编程上实现了完全对象化,提供了对同步机制的良好支持。
  在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。管道方法不建议使用,阻塞队列方法在问题4已有描述,现只提供前两种实现方法。
  - 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 list = new LinkedList();
  // 生产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 getList() {
  return list;
  }
  public void setList(LinkedList list) {
  this.list = list;
  }
  public int getMAX_SIZE() {
  return MAX_SIZE;
  }
  }
  ```
  仓库类:(await()/signal()方法)
  ```
  public class Storage { // 仓库最大存储量
  // 仓库最大存储量
  private final int MAX_SIZE = 100;
  // 仓库存储的载体
  private LinkedList list = new LinkedList();
  //
  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 getList() {
  return list;
  }
  public void setList(LinkedList list) {
  this.list = list;
  }
  }

精彩内容,一键分享给更多人!
收藏
收藏0
转播
转播
分享
淘帖0
支持
支持0
反对
反对0
回复

使用道具 举报

您需要登录后才可以回帖

本版积分规则

关注我们
千锋好程序员

北京校区(总部):北京市海淀区宝盛北里西区28号中关村智诚科创大厦

深圳西部硅谷校区:深圳市宝安区宝安大道5010号深圳西部硅谷B座A区605-619

杭州龙驰智慧谷校区:浙江省杭州市下沙经济技术开发区元成路199号龙驰智慧谷B座7层

郑州校区:郑州市二七区航海中路60号海为科技园C区10层、12层

Copyright 2007-2019 北京千锋互联科技有限公司 .All Right

京ICP备12003911号-5 京公安网11010802011455号

请您保持通讯畅通1对1咨询马上开启