总结lab6 ADT设计方案

    1. ADT设计方案

设计了哪些ADT、各自的作用、属性、方法;

. Monkey

猴子类。继承Thread。

作用:每个猴子为一个线程,对于一只猴子在某时刻选择并爬上某个梯子,意味着它跳到第 1 个踏板上。猴子一旦上了某个梯子,就不能在中途跳到别的梯子上。当猴子跳出梯子,该线程结束。

 

fields:

       private final int id;  //num of monkey

       private final String direction;  //initially L or R

       private int v;  //speed

       private int position = 0; //position in the ladder

       private final int produceTimer;  //timer to record produceTime

       private int now;  //timer to record the elapsed time

 

       private boolean finished = false;  //Whether it has passed the ladder

 

       private Strategy ladderStratrgy;  //strategy of choosing ladder

       private Ladder ladder = null;  //Ladder being used

 

方法:

// getters方法

// setters方法

 

主要的方法是重写run

1. 方法开始要根据策略选择梯子,传入的参数是猴子的direction,返回的是选到的梯子对象或null,如果返回为null,则线程sleep 1秒,while循环中下一秒继续选择梯子。

ladder = this.ladderStratrgy.chooseLadder(this.direction);  //选梯子

2. 如果选到了不为null的梯子,调用Ladder类中的方法使猴子上梯子。

ladder.upLadder(this);    //上梯子

3. 接下来又是一个while循环,判断的是猴子的状态finished是否为true,while循环的内部调用Ladder.cross(this)使猴子不断在梯子上移动,如果猴子的位置超出了梯子的长度,则finished变为true,且猴子下梯子。

总结lab6 ADT设计方案

. Ladder

梯子类。

作用:梯子提供了猴子过桥的工具,其中包含了猴子选踏板、上梯子、过梯子、下梯子等方法。

 

fileds:

       private int leftCrossing = 0; //monkeys from the left direction

       private int rightCrossing = 0; //monkeys from the right direction

       private int[] pedals = new int[CrossingSimulator.h + 10]; //pedals free or occupied

       private final int id; //number of ladder

 

方法:

//getters

//setters

其中getters和setters都是被synchronized修饰的方法,这些方法为同步方法,synchronized作用的范围是整个方法,作用的对象是调用这个方法的Ladder对象;

 

public synchronized void upLadder(Monkey monkey)

该方法为猴子上梯子,synchronized修饰的同步方法,如果猴子的方向是L->R,则leftCrossing++,否则rightCrossing++。

总结lab6 ADT设计方案

public void cross(Monkey monkey)

该方法为猴子过梯子,针对这个方法,为了提高线程并行的效率,未使用synchronized方法修饰方法,而是修饰一个代码块,为同步语句块,其作用的范围是大括号{}括起来的代码,加锁的对象还是ladder。

先根据梯子上的占用情况选择踏板,将猴子的原位置设置为0,将猴子的新位置设置为1,并且猴子内部的position也更新。执行这步需要1s,因此需要将猴子现在的时钟加1s。

总结lab6 ADT设计方案

public synchronized void exit(Monkey monkey)

该方法为猴子下梯子,synchronized修饰的同步方法,如果猴子的方向是L->R,则leftCrossing--,否则rightCrossing--。梯子某个方向的猴子数量减一,并且猴子离开梯子前的最后一块踏板设置为0。

 

private int choosePedal(Monkey monkey)

猴子选择踏板。先获得猴子此时的位置,和其速度(最大可能移动距离)。

我们需要讨论猴子的最大可能移动的位置是否会超出梯子,如果不会超出梯子,再讨论移动范围内前面是否有猴子,如果没有,返回最远可能踏板,如果有,返回没有猴子的最近踏板,并且猴子速度需要降低。如果会超出梯子,再讨论梯子前面是否有猴子,如果有,则返回梯子最远距离,如果没有,返回最远可能踏板,并且猴子速度需要降低。

方法的内部,多重if else讨论的语句块中需要对pedals进行加锁。

总结lab6 ADT设计方案

. CrossingSimulator

过河模拟器。

作用:实现与用户交互,读入用户输入的参数或v3中的文件,获得实验中monkey和ladder的参数。

 

fields:

       public static final int h = 20; //length of ladders

       public static int n; //quantity of ladders

       public static ArrayList<Monkey> monkeyList = new ArrayList<Monkey>(); //list to store monkeys

       public static ArrayList<Ladder> ladderList = new ArrayList<Ladder>(); //list to store ladders

       public static final Logger log = Logger.getLogger(CrossingSimulator.class.getSimpleName());  //logging

       public static double extraTime = 0;  //time spent on GUI and log

 

方法:

main()

读入用户输入猴子生成器需要的参数

总结lab6 ADT设计方案

写日志,新建一个猴子生成器,在其produce方法中传入参数。

总结lab6 ADT设计方案

 

 

. MonkeyGenerator

猴子生成器。

1. 在猴子生成器MonkeyGenerator中只有一个方法,

public void produce(int n, int h, int t, int monkeyQuantity, int k, int mv , int s)

其中方法的参数由用户输入后传入,分别为梯子数n,阶梯数h(固定为20),产生猴子间隔秒数t,猴子总数,一次产生的猴子数量,猴子的最大速度,策略(猴子过河模拟器v2中使用)。

2. 得到这些参数后,我们需要随机生成猴子的信息,猴子的ID就在根据猴子对象产生的顺序编号。其他的信息,把猴子的两个方向放到一个集合中,把三种策略的对象放在一个集合中,然后以如下的形式产生随机数,即可在集合中随机获得属性。

Random random = new Random();

                 int rd = random.nextInt(2);

 

3. 至于产生猴子的时间和数量,则根据传入的参数t、k和monkeyQuantity,使用一个两重循环即可。另外,如果monkeyQuantity/????不为整数,则最后一次产生的猴子个数为monkeyQuantity%????。

总结lab6 ADT设计方案

给出每个ADT的specification;

Ladder:对于梯子类,还需要保证线程安全

总结lab6 ADT设计方案

 

Monkey:

总结lab6 ADT设计方案

 

CrossingSimulator:

总结lab6 ADT设计方案