当前位置: 首页 > 知识库问答 >
问题:

Java线程忙着等待

魏雅惠
2023-03-14

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

该项目希望做到以下几点:早上,学生醒来后(这需要一段随机的时间),他会去洗手间为新的上学日做准备。如果浴室已经客满,学生需要Rest一下(使用yield()),然后他会等待(使用busy waiting),等待浴室可用。学生将以先到先得的方式使用浴室(您可以使用布尔数组/向量将其按顺序释放)。

 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;

这是我的主要方法,它允许用户指定他们想要多少学生线程。是的,我不明白如何实现值的改变,以便繁忙的wait 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();
   }

共有1个答案

申高峯
2023-03-14

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

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

需要同步,否则在执行(2)之前,两个线程可能会在(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位女士< br >玛西娅睡了3357位女士< br >爱丽丝睡了1289位女士< br >彼得睡了820位女士< br >德斯蒙德睡了1878位女士< br >索菲亚睡了2274位女士< br >彼得去了洗手间< br >彼得去了洗手间< br >爱丽丝去了洗手间< br >爱丽丝Rest了一会儿< br >彼得去了大学< br >德斯蒙德去了洗手间< br >德斯蒙德去了洗手间< br >鲍勃去了洗手间< br 去上大学鲍勃在洗手间索菲亚Rest爱丽丝去上大学玛西娅在洗手间玛西娅去上大学

 类似资料:
  • 我正在阅读Java中的TCP/IP套接字,关于服务器套接字,它说 当我们在该ServerSocket实例上调用接受()时,如果新连接挂起,接受()立即返回;否则它会阻塞,直到连接进入或计时器到期,以先到者为准。这允许单个线程处理多个连接。不幸的是,这种方法要求我们不断轮询所有I/O源,而这种“忙等待”方法再次引入了大量开销,因为循环遍历连接只是为了发现它们无事可做。 据我所知,当连接到来时,是否应

  • 问题内容: 我有以下情况: 为了运行算法,我必须运行多个线程,并且每个线程都会在死之前设置一个实例变量x。问题是这些线程不会立即返回: 我应该使用等待通知吗?还是我应该嵌入一个while循环并检查是否终止? 感谢大家! 问题答案: 创建一些共享存储来保存每个线程的值,或者如果足够的话,只存储总和。使用a 等待线程终止。每个线程完成后都会调用,您的方法将使用该方法来等待它们。 编辑: 这是我建议的方

  • 我的问题在定义上有点挑剔: 下面的代码可以用“忙着等待”来形容吗?尽管它使用thread.sleep()来允许上下文切换? PS--维基百科目前对忙碌等待的定义表明,忙碌等待是一种“不太浪费”的形式。

  • 问题内容: 我正在为我的ubuntu服务器(针对我的多客户端匿名聊天程序)实现一种简单的线程池机制,并且需要使我的工作线程进入睡眠状态,直到需要执行一项工作(以函数指针和参数的形式) 。 我当前的系统即将关闭。我(工人线程正在)问经理是否有工作可用,以及是否有5毫秒没有睡眠。如果存在,请将作业添加到工作队列中并运行该函数。糟糕的循环浪费。 什么我 喜欢 做的是做一个简单的事件性的系统。我正在考虑有

  • 问题内容: 问题描述 : - 步骤1: 在主线程中从用户那里获取输入FILE_NAME。 步骤2: 对该文件执行10个操作(即,计数字符,计数行等。),所有这10个操作必须位于单独的线程中。这意味着必须有10个子线程。 步骤3: 主线程等待,直到所有那些子线程完成。 步骤4: 打印结果。 我做了什么 :- 我用3个线程做了一个示例代码。 我不希望您遇到文件操作代码。 问题:- 我上面的代码没有给出

  • 我有一个写文件的方法,它可能有点慢。因此,我这样做是为了避免阻止其他操作: 然而,直到在a之后执行B之后,仍然需要一段时间,我想知道是否应该这样做: 或者,换句话说,调用一个内部有线程的方法是否意味着等待该方法结束,从而等待线程结束? 只是为了澄清一些事情:我想知道两个选项是否相同,或者在第一个选项中,线程是否应该完成以启动B指令。