千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  行业资讯  > Java开发面试题:如何保证同一资源被多个线程并发访问时的完整性?

Java开发面试题:如何保证同一资源被多个线程并发访问时的完整性?

来源:千锋教育
发布人:千锋老师
时间: 2019-02-25 14:55:00 1551077700

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

  }

  }

 

tags:
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT
开班信息
北京校区
  • 北京校区
  • 大连校区
  • 广州校区
  • 成都校区
  • 杭州校区
  • 长沙校区
  • 合肥校区
  • 南京校区
  • 上海校区
  • 深圳校区
  • 武汉校区
  • 郑州校区
  • 西安校区
  • 青岛校区
  • 重庆校区
  • 太原校区
  • 沈阳校区
  • 南昌校区
  • 哈尔滨校区