全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  行业资讯

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

发布时间:2019-02-25 14:55:00
发布人:千锋老师

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

  }

  }

 

相关文章

PMP®认证荣获北京市境外职业资格认可!

2023-09-07

有哪些好的HTML5前端开发培训机构?

2023-09-07

怎么选择适合自己的HTML5前端开发培训机构?

2023-09-07

短视频运营哪个培训机构靠谱?

2023-09-07

怎么选择靠谱的短视频运营培训机构?

2023-09-07

短视频运营哪个培训机构好?

2023-09-07
在线咨询 免费试学 教程领取