nachos-java Task1.6 Boat Program

来源:互联网 发布:网络lw代表什么意思 编辑:程序博客网 时间:2024/06/06 00:10

Boat Program

  • 实验要求
  • 实验关键代码
  • 关键代码分析
  • 实验测试代码
  • 测试结果

实验要求

• A number of Hawaiian adults and children are trying to get from Oahu to Molokai. Unfortunately, they have only one boat which can carry maximally two children or one adult. The boat can be rowed back to Oahu, but it requires a pilot to do so
• Arrange a solution to transfer everyone from Oahu to Molokai. You may assume that there are at least two children
• The method Boat.begin() should fork off a thread for each child or adult—–parent thread
• Your mechanism cannot rely on knowing how many children or adults are present beforehand
• To show that the trip is properly synchronized, make calls to the appropriate BoatGrader methods every time someone crosses the channel
• When a child pilots the boat from Oahu to Molokai, call ChildRowToMolokai. When a child rides as a passenger from Oahu to Molokai, call ChildRideToMolokai
• Make sure that when a boat with two people on it crosses, the pilot calls the …RowTo… method before the passenger calls the … RideTo … method
• Your solution must have no busy waiting, and it must eventually end
• The idea behind this task is to use independent threads to solve a problem
• You are to program the logic that a child or an adult would follow if that person were in this situation.
• It is reasonable to allow a person to see how many children or adults are on the same island they are on
• A person could see whether the boat is at their island
• A person can know which island they are on
• All of this information may be stored with each individual thread or in shared variables
• So a counter that holds the number of children on Oahu would be allowed, so long as only threads that represent people on Oahu could access it

实验关键代码

关键代码在Boat类中

  • 变量声明
static BoatGrader bg;static boolean boatInO;static int num_children_O;static int num_alduts_O;static int num_children_M;static int num_alduts_M;static Lock lock;static Condition children_condition_o;static Condition children_condition_m;static Condition alduts_condition_o; static boolean gameover;static boolean is_pilot;static boolean is_adult_go;
  • 方法实现
public static void begin( int adults, int children, BoatGrader b )    {    bg = b;num_children_O=children;num_alduts_O = adults;num_alduts_M = 0;num_children_M = 0;boatInO = true;lock = new Lock();children_condition_o = new Condition(lock);children_condition_m = new Condition(lock);alduts_condition_o = new Condition(lock);gameover = false;is_pilot = true;is_adult_go = false;for(int i = 0;i<adults;i++){//每个大人为一个线程    new KThread(new Runnable(){        public void run(){            AdultItinerary();        }    }).fork();;}for(int i = 0;i<children;i++){//每个小孩为一个线程    new KThread(new Runnable(){        public void run(){            ChildItinerary();        }    }).fork();;}}static void AdultItinerary(){    bg.initializeAdult();     lock.acquire();//申请锁    if(!(is_adult_go&&boatInO)){//如果大人不走,或者船不在O岛,则大人睡眠        alduts_condition_o.sleep();    }    bg.AdultRowToMolokai();//否则大人划至M岛    num_alduts_M++;//M岛的大人数量+1    num_alduts_O--;//O岛的大人数量—1    //is_adult_go = false;    boatInO = false;//船改至M岛    children_condition_m.wake();//唤醒M岛的孩子线程    is_adult_go = false;//下一次船再到O岛时,必定是小孩走    lock.release();//释放锁}static void ChildItinerary(){    bg.initializeChild();     lock.acquire();//申请锁    while(!gameover){        if(boatInO){//如果船在O岛            if(is_adult_go){//如果大人能走,则将O岛的大人线程唤醒,O岛的孩子线程睡眠                alduts_condition_o.wake();                children_condition_o.sleep();            }            if(is_pilot){//如果是第一个小孩,则设为舵手                bg.ChildRowToMolokai();                num_children_O--;//O岛小孩数量-1                num_children_M++;//M岛小孩数+1                is_pilot = false;//将舵手设为false                children_condition_o.wake();//唤醒O岛的其他小孩线程                children_condition_m.sleep();//让自己睡眠在M岛            }else{//如果是第二个小孩,则设为游客                bg.ChildRideToMolokai();                boatInO = false;//将船改为在M岛                //is_on_O = false;                num_children_O--;//O岛的小孩数量-1                num_children_M++;//M岛的小孩数量+1                is_pilot=true;//将舵手设为true                if(num_alduts_O==0&&num_children_O==0){//如果O岛的孩子和大人数量均为0,则游戏结束                    gameover = true;                }                if(gameover){//如果游戏结束,则打印成功过河                    System.out.println("成功过河!!!");                    children_condition_o.sleep();                }                if(num_alduts_O!=0&&num_children_O==0){//如果O岛的大人还有,但小孩线程为0,则大人可走                    is_adult_go = true;                }                children_condition_m.wake();//将M岛的其他孩子线程唤醒                children_condition_m.sleep();//将自己睡眠在M岛            }        }else{//如果船在M岛            bg.ChildRowToOahu();            //is_on_O = true;            boatInO = true;//设置船在O岛            num_children_O ++;//O岛孩子数量+1            num_children_M --;//M岛孩子线程数量-1            if(is_adult_go){//如果大人可以走,则将O岛的大人线程唤醒                alduts_condition_o.wake();            }else{//否则,唤醒O岛的孩子线程                children_condition_o.wake();            }            children_condition_o.sleep();//让自己睡眠在O岛        }    }    lock.release();//释放锁    }

实验测试代码

public static void selfTest()    {    BoatGrader b = new BoatGrader();//  System.out.println("\n ***Testing Boats with only 2 children***");//  begin(0, 2, b);    System.out.println("\n ***Testing Boats with 2 children, 1 adult***");    begin(1, 2, b);//      System.out.println("\n ***Testing Boats with 3 children, 3 adults***");//      begin(3, 3, b);}

关键代码分析

  • 思路分析

    该task最重要的是读懂题意,想清楚过河策略。在我的代码实现中,采取的策略很简单,一句话概括就是:让孩子尽可能的过河。下面我来解释一下这句话。只要O岛孩子够两个,就过河,否则,让大人过河;而在如果船在M岛更简单,只能孩子回来。孩子回来之后看0岛小孩人数,如果够两个,这两个孩子走,否则,大人过河,再回来一个孩子。如此反复,知道O岛没有小孩也没有大人,则游戏结束。
  • 方法解释

    该task主要需要编写三个方法,我来一一解释:1、void begin()方法   在该方法中,主要需要做两件事,一、将全局变量实例化;二、为每个大人或小孩创建线程,并将线程启动。 2、void AdultItinerary()方法    该方法是大人线程启动后调用的方法,核心是一个分支。    如果满足大人过河的条件,则将相关变量进行更改,比如更改M岛和O岛的大人数量(num_alduts_M++;num_alduts_O--;),更改船的位置(boatInO = false;),更改大人可否过河的标记(is_adult_go = false;),并在方法最后唤醒M岛的孩子线程(children_condition_m.wake());    如果不满足大人过河的条件,则将该大人线程睡眠在O岛,在睡眠前将O岛的孩子线程唤醒。     3、void ChildItinerary()方法      该方法是小孩线程启动后调用的方法。该方法较上一个方法而言,更为复杂一点。因为孩子在O岛和M岛均可过河,同时,过河时为两个人,一个为舵手,一个为游客。      由于孩子线程在M岛仍有可能过河(返回O岛),所以孩子线程需要在一个循环中,在我的代码中使用while(!gameover)来实现。      进入循环后有一个分支,如果船在O岛,则判断大人过河条件是否满足,若满足,将大人线程唤醒,然后将该孩子线程睡眠在O岛。否则两个孩子过河。      如果船在M岛,则一个孩子过河返回O岛。更改相关变量:船的位置(boatInO = true;);O岛和M岛的孩子数量(num_children_O ++;num_children_M --;);然后判断如果满足大人过河的条件,则将大人线程唤醒,否则唤醒O岛的孩子线程,然后将该线程睡眠在O岛。      其中两个孩子过河需要判断谁是舵手,谁是游客,在我的代码实现中,采用第一个唤醒的孩子线程为舵手,第二个为游客。

测试结果

1、只有两个小孩过河
这里写图片描述
2、1个大人和2个小孩过河
这里写图片描述
3、3个大人和3个小孩过河
这里写图片描述

0 0
原创粉丝点击