繁体   English   中英

Java线程忙于等待

[英]Java Threads Busy Waiting

嗨,我正在做一个项目,但是我已经陷入了非常困惑的境地。 我试图寻找方法来学习如何编写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;

这是我的主要方法,它允许用户指定所需的学生线程数。 是的,我不明白如何实现值的更改,这样可以打破繁忙的while while循环。

 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();
   }

这是繁忙等待的工作示例。 它使用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 ,否则有可能两个线程在执行( (2) (1)之前通过(1)的测试成功(因为这两个操作不是原子的 ),然后两个人会一起进入洗手间...

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();
    }

}

可能的输出:

鲍勃睡了2128毫秒
玛西娅入睡3357毫秒
爱丽丝睡了1289毫秒
彼得睡了820毫秒
德斯蒙德睡了1878毫秒
索菲亚(Sophia)睡2274毫秒
彼得去洗手间
彼得在洗手间
爱丽丝去洗手间
爱丽丝休息一下
彼得上大学
戴斯蒙德去洗手间
戴斯蒙德在浴室
鲍勃去洗手间
鲍勃休息一下
索菲亚去洗手间
索菲娅休息一下
爱丽丝休息一下
戴斯蒙德上大学
鲍勃在洗手间
索菲娅休息一下
爱丽丝休息一下
玛西娅去洗手间
玛西娅休息一下
鲍勃上大学
索菲娅在浴室里
爱丽丝休息一下
玛西娅休息一下
索菲亚上大学
爱丽丝在浴室
玛西娅休息一下
爱丽丝上大学
玛西娅在浴室
玛西娅上大学

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM