使用信号量的Java Unisex浴室程序 - 逻辑问题

时间:2016-03-20 22:06:54

标签: java logic semaphore

import java.util.concurrent.Semaphore;
public class UnisexBathroom{
   static Semaphore bathroom;
   static Semaphore men_only;
   static Semaphore women_only;
public static void main(String[] args){
    if (args.length != 2) {
        printUsage();
    }

    int totMen = 0;
    int totWomen = 0;

    try {
        totMen = Integer.parseInt(args[0]);
        totWomen = Integer.parseInt(args[1]);
    }
    catch (NumberFormatException e) {
        printUsage();
    }

    bathroom= new Semaphore(1);
    men_only= new Semaphore(1);
    women_only= new Semaphore(1);

    System.out.println("Working\t\tEntering\tIn Bathroom\tLeaving");
    System.out.println("----------------------------------------------------------");

    Thread[] men = new Thread[totMen];
    for (int i = 0; i < totMen; i++) {
        men[i] = new ManThread(i);
        men[i].start();
    }

    Thread[] women = new Thread[totWomen];
    for (int i = 0; i < totWomen; i++) {
        women[i] = new WomanThread(i);
        women[i].start();
    }

    for (int i = 0; i < totMen; i++) {
        try {
            men[i].join();
        }
        catch (InterruptedException e) {
        }
    }

    for (int i = 0; i < totWomen; i++) {
        try {
            women[i].join();
        }
        catch (InterruptedException e) {
        }
    }

    System.exit(0);
}

private static void printUsage() {
    System.out.println("Usage: java UnisexBathroom <totMen> <totWomen>");
    System.out.println("  <totMen>: Total number of men.");
    System.out.println("  <totWomen>: Total number of women.");
    System.exit(-1);
}

public static void randomSleep(int max) {
    try {
        Thread.sleep((int) (Math.random() * max));
    }
    catch (InterruptedException e) {
    }
}

private static class ManThread extends Thread {

    private int id;

    public ManThread(int id) {
        this.id = id;
    }

    public void run() {
        doWork();
        if(UnisexBathroom.men_only.availablePermits()==0){
           useBathroom();
        }//if
        else{   
        try{
        UnisexBathroom.bathroom.acquire();
        UnisexBathroom.men_only.acquire();
        }catch(InterruptedException e){
           System.out.println(e);
           System.exit(-1);
        }
        useBathroom();
        UnisexBathroom.men_only.release();
        UnisexBathroom.bathroom.release();
        }//else   
        doWork();           
    }//run

    private void doWork() {
        System.out.println("Man " + id);
        UnisexBathroom.randomSleep(10000);
    }

    private void useBathroom() {
        System.out.println("\t\tMan " + id);
        UnisexBathroom.randomSleep(100);
        System.out.println("\t\t\t\tMan " + id);
        UnisexBathroom.randomSleep(500);
        System.out.println("\t\t\t\t\t\tMan " + id);
        UnisexBathroom.randomSleep(100);
    }
}

private static class WomanThread extends Thread {

    private int id;

    public WomanThread(int id) {
        this.id = id;
    }

    public void run() {
        doWork();
        if(UnisexBathroom.women_only.availablePermits()==0){
           useBathroom();
        }//if
        else{   
        try{
        UnisexBathroom.bathroom.acquire();
        }catch(InterruptedException e){
           System.out.println(e);
           System.exit(-1);
        }  
        useBathroom();
        UnisexBathroom.women_only.release();
        UnisexBathroom.bathroom.release();
        }//else   
        doWork();
    }//run

    private void doWork() {
        System.out.println("Woman " + id);
        UnisexBathroom.randomSleep(10000);
    }

    private void useBathroom() {
        System.out.println("\t\tWoman " + id);
        UnisexBathroom.randomSleep(100);
        System.out.println("\t\t\t\tWoman " + id);
        UnisexBathroom.randomSleep(500);
        System.out.println("\t\t\t\t\t\tWoman " + id);
        UnisexBathroom.randomSleep(100);
    }
}

}

我的程序假设只允许男性或女性进入浴室,如果男性进入,那么只有另一名男性可以进入,反之亦然。我的问题是我正在使用我正在使用的信号量的正确方法来解决这个问题,如果我正确使用它们。这是我运行代码时发生的情况:results results

我很抱歉,如何正确格式化我的结果,所以我加入了超链接,但基本上当男人3,1和2进入男人1和2时,直到女人1进入后才离开,这意味着两个男人和一个女人们在浴室里不可能发生。重申一下,我是否正确地接受了逻辑错误或接近错误?

1 个答案:

答案 0 :(得分:0)

import java.sql.Timestamp;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.Scanner;

public class UnisexBathroom{
   static Semaphore bathroom;
   static Semaphore men_only;
   static Semaphore women_only;
public static void main(String[] args){
Scanner scIn = new Scanner(System.in);
int totMen = 0;
int totWomen = 0;
String Line;
    System.out.print("Total number of men:");
    totMen = scIn.nextInt();
    System.out.print("Total number of women:");
    totWomen = scIn.nextInt();
    Line = Rall(totMen,totWomen);
bathroom= new Semaphore(1);
men_only= new Semaphore(1);
women_only= new Semaphore(1);
System.out.println("m"+UnisexBathroom.men_only.availablePermits()+
                   "f"+UnisexBathroom.women_only.availablePermits()+
                   "b"+UnisexBathroom.bathroom.availablePermits());
System.out.println("Working\t\tEntering\tIn Bathroom\tLeaving");
System.out.println("----------------------------------------------------------");

Thread[] men = new Thread[Line.length()];
Thread[] women = new Thread[Line.length()];
for (int i = 0; i < Line.length(); i++) {
    if(Line.charAt(i)=='M'){
    men[i] = new ManThread(i);
    men[i].start();
    }
    if(Line.charAt(i)=='F'){
    women[i] = new WomanThread(i);
    women[i].start();
    }
}

for (int i = 1; i < Line.length(); i++) {
   if(Line.charAt(i)!=Line.charAt(i-1)){
        if(Line.charAt(i)=='M'){
            try {
                men[i].join();
            } catch (InterruptedException ex) {
                Logger.getLogger(UnisexBathroom.class.getName()).log(Level.SEVERE, null, ex);
            }

        }else{
            try {
                women[i].join();
            } catch (InterruptedException ex) {
                Logger.getLogger(UnisexBathroom.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
   }else{

   } 
}
System.exit(0);
}
private static String Rall(int x, int y){
String Output = "";  
Random rnd = new Random();
int male=0;
int female=0;
while(male!=x||female!=y){
    int R=rnd.nextInt(2);
    switch(R){
        case 0:
            if(male<x){
            Output=Output.concat("M");
            male++;}
            break;
        case 1:
            if(female<y){
            Output=Output.concat("F");
            female++;}
            break;
    }
} 
return Output;     
}

public static void randomSleep(int max) {
Random rnd = new Random();
int x = 1+rnd.nextInt(2);
try {
    Thread.sleep((int) (x* max));
}
catch (InterruptedException e) {
    System.out.println(e);
}
}

private static class ManThread extends Thread {
private int id;

public ManThread(int id) {
    this.id = id;
}

public void run() {
    doWork();
    if(UnisexBathroom.men_only.availablePermits()==0){
       useBathroom();
    }//if
    else{   
    try{
    UnisexBathroom.bathroom.acquire();
    UnisexBathroom.men_only.acquire();
    }catch(InterruptedException e){
       System.out.println(e);
       System.exit(-1);
    }
    try{
    useBathroom();
    }finally{
    UnisexBathroom.men_only.release();
    UnisexBathroom.bathroom.release();
    }//else   
    System.out.print("E");doWork();    
    }
}//run

private void doWork() {
    System.out.println("Man " + id);
    UnisexBathroom.randomSleep(10000);
}

private void useBathroom() {
    System.out.println("\t\tMan " + id );
    UnisexBathroom.randomSleep(1000);
    System.out.println("\t\t\t\tMan " + id );
    UnisexBathroom.randomSleep(3000);
    System.out.println("\t\t\t\t\t\tMan " + id );
    UnisexBathroom.randomSleep(1000);
}
}

private static class WomanThread extends Thread {
private int id;

public WomanThread(int id) {
    this.id = id;
}

public void run() {
    doWork(); 
    if(UnisexBathroom.women_only.availablePermits()==0){
       useBathroom();
    }//if
    else{   
    try{
    UnisexBathroom.bathroom.acquire();
    UnisexBathroom.women_only.acquire();
    }catch(InterruptedException e){
       System.out.println(e);
       System.exit(-1);
    }
    try{
    useBathroom();
    }finally{
    UnisexBathroom.women_only.release();
    UnisexBathroom.bathroom.release();
    }//else   
    System.out.print("E");doWork();    
    }
}//run

private void doWork() {
    System.out.println("Woman " + id);
    UnisexBathroom.randomSleep(10000);
}

private void useBathroom() {
    System.out.println("\t\tWoman " + id );
    UnisexBathroom.randomSleep(2000);
    System.out.println("\t\t\t\tWoman " + id );
    UnisexBathroom.randomSleep(5000);
    System.out.println("\t\t\t\t\t\tWoman " + id );
    UnisexBathroom.randomSleep(2000);
}
}
}

你错过了女人的遗嘱,我也改变了一点但是它仍然倾向于表明女人正在进入,而男人在卫生间退出之前就已进入。 (反之亦然)。