[软件构造]实验回顾:Lab6

实验目标:Multi-Thread Concurrent Programming

本次实验训练学生的并行编程的基本能力,特别是Java多线程编程的能力。根据一个具体需求,开发两个版本的模拟器,仔细选择保证线程安全(threadsafe)的构造策略并在代码中加以实现,通过实际数据模拟,测试程序是否是线程安全的。另外,训练学生如何在threadsafe和性能之间寻求较优的折中,为此计算吞吐率和公平性等性能指标,并做仿真实验。
⚫ Java多线程编程
⚫ 面向线程安全的ADT设计策略选择、文档化
⚫ 模拟仿真实验与对比分析

这次实验,难度偏大,debug过程极其复杂,好在代码量不是很大。

第一部分:ADT设计

ADT的设计,主要是猴子,梯子和猴子生成器的设计。
对于猴子,没什么特殊的,就是序号,速度,方向。
在这里插入图片描述
move方法:猴子在梯子上移动,需要考虑猴子到达对岸和猴子被阻挡两种情况,所以只能一步一步走。

  public synchronized int move(String direction, int position, int velocity) {
    int dest = position;
    if (direction.equals("L->R")) {
      for (int i = 1; i <= velocity; i++) {
        if (position + i > h) {
          dest = 0;
          break;
        } else if (!steps.containsKey(position + i)) {
          break;
        } else {
          dest++;
        }
      }
    } else {
      for (int i = 1; i <= velocity; i++) {
        if (position - i <= 0) {
          dest = 0;
          break;
        } else if (!steps.containsKey(position - i)) {
          break;
        } else {
          dest--;
        }
      }
    }
    if (dest != 0) {
      steps.put(dest, steps.get(position));
}
    if (dest != position) {
      steps.remove(position);
    }
    return dest;
  }

randomSpawnMonkey是随机分批生成猴子的方法,可以作为工厂方法使用。

 public void randomSpawnMonkey() {
    int num = 0;
    Random random = new Random();
    String direction = "R->L";
    for (int i = 0; i < Main.N / Main.k; i++) {
      for (int j = 0; j < Main.k; j++) {
        if (random.nextInt(2) == 0) {
          direction = "L->R";
        }
        int velocity = random.nextInt(Main.MV) + 1;
        Monkey monkey = new Monkey(num, direction, velocity);
        num++;
        monkey.start();
      }
      try {
        Thread.sleep(Main.t * 1000);
      } catch (Exception e) {
      }
    }
    for (int i = 0; i < Main.N % Main.k; i++) {
      if (random.nextInt(2) == 0) {
        direction = "L->R";
      }
      int velocity = random.nextInt(Main.MV) + 1;
      Monkey monkey = new Monkey(num, direction, velocity);
      num++;
      monkey.start();
    }
  }

第二部分:策略设计

采用Strategy设计模式,在两种策略之间自由切换。

  public static Strategy newStrategy(String choice) {
    if (choice.equals("Fast")) {
      return new Fast();
    } else if (choice.equals("Empty")) {
      return new Empty();
    } else {
      throw new RuntimeException();
    }
  }

在策略的选择上,我选择了两种比较容易编写和实现的策略:
(1)优先选择整体推进速度最快的梯子
(2)先选择没有猴子的梯子,若所有梯子上都有猴子,则在岸边等待,直到某个梯子空闲出来。
具体实现不在此赘述。

第三部分:确保线程安全

1.使用private,限制其他类对数据的访问
2.设计Immutable的ADT
3.使用线程安全的mutable类型
4.使用同步的机制
这些都是保证线程安全的重要方法,在多线程程序中应用的十分广泛。如果我能在刚开始设计的时候尽多做到这些,就不会花费那么多时间去debug了。

第四部分:度量与日志

这部分,日志没什么可说的,在以前的实验里边已经操作过了,这次就是照葫芦画瓢。
对于吞吐率和公平性的度量,按照公式计算就可以了。
在分析各个变量对吞吐率和公平性的影响时,可以用图表的形式来直观的看,然后再从理论上分析。
结果:
1.吞吐率与策略有关。上面的分析指出,Fast策略中,多个猴子可以排队前进,而Empty策略只能是一个猴子独占一个梯子。所以Fast策略一定不比Empty策略吞吐率低。实验也支持这一点。
2.吞吐率与各参数的关系:吞吐率与N, MV, k, n正相关,与t负相关。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值