0

嗨,我正在做一个项目,但我已经到了一个非常困难的地方。我试图寻找方法来学习如何为繁忙的等待编写 while 循环,但我没有找到任何东西,我的代码只是作为无限循环运行。有人可以帮我解释一下繁忙的等待循环应该如何工作并帮助我摆脱这个无限循环吗?

该项目希望发生以下情况:早上,学生醒来后(需要随机时间),他将前往洗手间为新的上学日做准备。如果卫生间已经被占用,学生会休息一下(使用 yield()),稍后他将等待(使用忙等待)等待卫生间可用。学生将按照先到先得的原则使用浴室(您可以使用布尔数组/向量让它们按顺序释放)。

 public class Student implements Runnable 
    {
        private Random rn = new Random();
        private String threadNum;
        private volatile boolean bathroomFull = false;
        private static long time = System.currentTimeMillis();
        private Thread t;


    public Student(String studentID) 
    {
      threadNum = studentID;

      t = new Thread(this, "Student Thread #"+threadNum);
      System.out.println("thread created = " + t);
      // this will call run() function
      t.start();
   }

   public void run() 
   {
       int waitTime = rn.nextInt(4000 - 2000 + 1)+2000;

        System.out.println( "the current time is " + (System.currentTimeMillis() - time) + "and the wait time is: " +waitTime );

         //Student wakes up after random time
        while((System.currentTimeMillis()-time) < waitTime)
       {
          // System.out.println("the remaining sleep time is " + (System.currentTimeMillis()-time));
            ;
       }

      int a = rn.nextInt(4000 - 2000 + 1)+2000;
      try 
      {
          //System.out.println("I'm going to sleep for " +a + " milliseconds");
        Thread.sleep(a);
      } 
      catch (InterruptedException e) 
      {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      //this is the busy wait loop where is the bathroom is full then a thread will yield until it is available
    int l = rn.nextInt(10 - 1)+1;
  bathroomFull = true;

      while(bathroomFull)
        {
          for(int j = 0; j < l; j++)
          {
              System.out.println("i am in the bathroom for " + l + "minutes " + Thread.currentThread());
          }
          Thread.yield();
          bathroomFull = false;
          //exitBathroom();

        }
    bathroomFull = true;

这是我的主要方法,它允许用户指定他们想要多少个学生线程。是的,我不明白如何实现值的更改,以便可以打破繁忙的等待循环。

 public static void main(String args[]) 
   {
       int numberOfStudents;
       numberOfStudents = Integer.parseInt(JOptionPane.showInputDialog("How many students are there in the university? "));
      // System.out.println("there are " + numberOfStudents);

       for(int i = 0; i < numberOfStudents; i++)
       {   
           new Student(String.valueOf(i+1));
       }
          new Teacher();
   }
4

1 回答 1

0

这是一个忙碌等待的工作示例。它使用 AtomicBoolean 来指示浴室是否被占用。原子操作是一步执行的,这对于保证线程安全很重要。我们也可以使用普通的布尔值并compareAndSet自己编写:

private static synchronized boolean compareAndSet(boolean expected, boolean value) {
    if (occupied == expected) { // (1)
        occupied = value; // (2)
        return true;
    } else {
        return false;
    }
}

这是 Java 实现的等价物(对于本示例)。synchronized是必需的,否则有可能两个线程在执行(1)之前成功测试(2)(因为这两个操作不是原子的)然后两个人会一起去洗手间......

import java.util.concurrent.atomic.AtomicBoolean;

public class Student extends Thread {

    // note the static: there is only one bathroom for all students
    private static AtomicBoolean occupied = new AtomicBoolean(false);

    private String name;

    public Student(String name) {
        this.name = name;
    }

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            System.out.println(name + " wet his/her pants");
        }
    }

    @Override
    public void run() {
        int r = (int)(Math.random() * 5000);
        System.out.println(name + " sleeps for " + r + " ms");
        sleep(r);
        System.out.println(name + " goes to bathroom");
        // ***** busy wait *****
        while (!occupied.compareAndSet(false, true)) {
            System.out.println(name + " takes a break");
            Thread.yield();
            sleep(1000);
        }
        // ***** end (in bathroom) *****
        System.out.println(name + " is in the bathroom");
        sleep(1000);
        occupied.set(false);
        System.out.println(name + " goes to university");
    }

    public static void main(String[] args) {
        new Student("Bob").start();
        new Student("Alice").start();
        new Student("Peter").start();
        new Student("Marcia").start();
        new Student("Desmond").start();
        new Student("Sophia").start();
    }

}

可能的输出:

Bob 睡了 2128 ms Marcia 睡 了
3357 ms Alice
睡了 1289 ms Peter 睡
了 820 ms
Desmond 睡了 1878 ms
Sophia 睡了 2274 ms大学 Desmond 去洗手间 Desmond 在洗手间 Bob 去洗手间 Bob 休息一下 Sophia 去洗手间 Sophia 休息一下 Alice 休息一下 Desmond 去大学 Bob 在洗手间 Sophia 休息一下 Alice 休息一下 Marcia 去浴室

















Marcia 休息
Bob 去上大学
Sophia 在卫生间
Alice 休息
Marcia 休息
Sophia 去大学
Alice 在卫生间
Marcia 休息
Alice 去大学
Marcia 在卫生间
Marcia 去大学

于 2015-04-26T01:08:08.833 回答