• 在线客服

  • 扫描二维码
    下载博学谷APP

  • 扫描二维码
    关注博学谷微信公众号

  • 意见反馈

原创 【Java面试题】如何保障同一资源被多个线程并发方位时的完整性?

发布时间:2019-06-12 17:39:36 浏览 5812 来源:博学谷资讯 作者:枫调

      作为技术岗,进入一家企业不但要经历面试,还会有一些笔试题目。通过整理发现“如何保障同一资源被多个线程并发方位时的完整性?”是被提问次数比较多的问题。今天就和大家一起来学习一下这个面试题的解决方案。

     

    【Java面试题】如何保障同一资源被多个线程并发方位时的完整性?

     

      常用的同步方法是采用信号或加锁机制,确保资源在任意时刻至多被一个线程访问。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;

    }

     

    以上就是“如何保障同一资源被多个线程并发方位时的完整性?”的解决方案。关注博学谷资讯页面,后期会为大家提供更多的关于java面试的题目以及解析。

    申请免费试学名额    

在职想转行提升,担心学不会?根据个人情况规划学习路线,闯关式自适应学习模式保证学习效果
讲师一对一辅导,在线答疑解惑,指导就业!

上一篇: 初级Java程序员需要注意的问题 下一篇: 自学Java开发方法有哪些?如何高效自学

相关推荐 更多

热门文章

  • 前端是什么
  • 前端开发的工作职责
  • 前端开发需要会什么?先掌握这三大核心关键技术
  • 前端开发的工作方向有哪些?
  • 简历加分-4步写出HR想要的简历
  • 程序员如何突击面试?两大招带你拿下面试官
  • 程序员面试技巧
  • 架构师的厉害之处竟然是这……
  • 架构师书籍推荐
  • 懂了这些,才能成为架构师
  • 查看更多

扫描二维码,了解更多信息

博学谷二维码