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

仅使用通知方法恢复处于等待状态的所有线程

谭修然
2023-03-14

我只想使用notify方法恢复所有进入等待状态的线程。我不想使用notifyAll()恢复所有处于等待状态的线程。

public class MultithreadingTest{
    public static void main(String[] args) throws  Exception{
        SharedResource sr = new SharedResource();
        sr.isWaiting = true; // to make thread to go in waiting state
        Thread t1 = new Thread(sr);
        Thread t2 = new Thread(sr);
        Thread t3 = new Thread(sr);
        t1.start();
        t2.start();
        t3.start();
        sr.isWaiting = false; // to directly call the notify() based on condition
        Thread t6 = new Thread(sr);
        t6.start();
    }
}

class SharedResource implements Runnable{
    volatile boolean isWaiting;
    public void run(){
        System.out.println(Thread.currentThread().getName() + " enters with status " + this.isWaiting);
        synchronized (this){
            try {
                if(this.isWaiting) {
                    System.out.println(Thread.currentThread().getName() + " goes into waiting stage");
                    wait(); // Release the lock so other threads can acquire it
                    System.out.println(Thread.currentThread().getName() + " wakes up");
                } else {
                    System.out.println(Thread.currentThread().getName() + " calling the notify method");
                }
                notify(); // Notifying the random thread which is in waiting state to resume again
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

调用 wait() 将释放内部锁,以便队列中的其他线程可以获取它。我希望最后一个线程直接调用 notify(),这将通知任何处于等待状态的线程再次恢复。等待线程唤醒并调用 notify(),这将再次恢复处于等待状态的线程。

共有1个答案

荆运诚
2023-03-14

在本例中,我们希望按以下顺序执行这些操作:

    < li >生成线程T1、T2和T3,并让这三个线程在共享资源上Hibernate < li >更改易变标志,并生成T4 < li>T4进入临界区,唤醒一个Hibernate线程,然后退出 < li >收到通知后,每个线程只通知一次,然后退出

上面的代码几乎是正确的,但是由于< code>main方法是由“main”线程执行的,我们必须确保线程T1、T2和T3在生成线程T4之前处于等待状态。我们可以通过使用信号量来做到这一点。< code >主线程将阻塞< code>semaphore.acquire()调用,直到所有线程都处于正确的状态。

请注意,由于竞争,在上面的代码中,线程T1可能在标志设置为false后进入关键部分,因此我们将失去对操作顺序的控制。

请参阅下面的更新代码,它将输出类似

main thread starts
Thread-2 enters with status true
Thread-2 goes into waiting stage
Thread-1 enters with status true
Thread-1 goes into waiting stage
Thread-0 enters with status true
Thread-0 goes into waiting stage
Thread-3 enters with status false
Thread-3 calling the notify method
Thread-3 terminates
main thread terminates
Thread-2 wakes up
Thread-2 terminates
Thread-1 wakes up
Thread-1 terminates
Thread-0 wakes up
Thread-0 terminates

代码

package sample;

import java.util.concurrent.Semaphore;

public class MultithreadingTest {
  public static void main(String[] args) throws Exception {
    System.out.println("main thread starts");
    SharedResource sr = new SharedResource();
    // to make thread to go in waiting state
    sr.isWaiting = true;
    Thread t1 = new Thread(sr);
    Thread t2 = new Thread(sr);
    Thread t3 = new Thread(sr);
    t1.start();
    t2.start();
    t3.start();

    // let the main thread wait, until all 3 threads reach the checkpoint
    sr.numWaiting.acquire(3);
    sr.isWaiting = false; // to directly call the notify() based on condition
    Thread t6 = new Thread(sr);
    t6.start();
    System.out.println("main thread terminates");
  }
}

class SharedResource implements Runnable {
  // keep a count of how many threads entered the critical section
  // needed by the main thread to know when to start the "wake-up" thread
  Semaphore numWaiting = new Semaphore(0);
  volatile boolean isWaiting;

  public void run() {
    System.out.println(Thread.currentThread().getName() + " enters with status " + this.isWaiting);
    synchronized (this) {
      try {
        if (this.isWaiting) {
          System.out.println(Thread.currentThread().getName() + " goes into waiting stage");
          numWaiting.release(1);
          wait(); // Release the lock so other threads can acquire it
          System.out.println(Thread.currentThread().getName() + " wakes up");
        } else {
          System.out.println(Thread.currentThread().getName() + " calling the notify method");
        }
        notify(); // Notifying the random thread which is in waiting state to resume again
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(Thread.currentThread().getName() + " terminates");
    }
  }
}
 类似资料:
  • 用例:每次我需要处理一个作业时创建一个新线程。 目前的实现:我使用的执行器服务与固定大小的线程池,例如50。对于每个作业,我都向executor服务提交一个新线程。 我试图实现的行为更像是自动伸缩。在高峰时间跨越更多的服务器(在本例中是线程)。并在负载不是很高的时候终止额外的服务器并保持最小的服务器计数。

  • 我们在其中一个模块中使用了Hystrix-断路器模式[library]。usecase是:-我们正在从kafka轮询16个消息,并使用pararllel流处理它们,因此,对于工作流中的每条消息,它需要3个rest调用,这些调用由hystric命令保护。现在,问题是当我尝试运行单个实例时,CPU显示尖峰,线程转储显示许多线程处于等待状态,等待所有3个命令。如下所示:-

  • 我还发现这个帖子在sun.misc.unsafe.park(本地方法)等待,但它对我的情况没有帮助。 在这种情况下,我还可以调查什么来获得更多细节?

  • 我对通知方法的一点感到困惑。“notify() :它唤醒一个在同一对象上调用 wait() 的线程。因此,假设两个线程称为等待同一对象。那么当我调用通知时,将通知哪个线程?

  • 我用绝地武士连接redis服务器。Redis ip值在一个单独的文件中配置,我试图在初始化期间加载该文件 我从redis获取多个密钥的方法如下 当我在属性文件中给出了不正确的ip值时,访问它的请求线程等待了很长一段时间。我的请求不应该因为池中资源不可用而停止。 在这里,我附加了停顿线程的线程转储(即;处于等待状态的线程) 我怎样才能做到这一点?非常感谢您的帮助。提前感谢:-)

  • 我有一段代码 如您所见,我首先将标志设置为false,这样其中一个线程就可以进入Sum2Elements方法并将其更改为true,从而让所有人都等待。 我知道在同步代码中,只有一个线程可以完成它的任务,这里我有两个同步方法,这是否意味着两个线程在每次通知之后都在尝试执行这个方法? 如果是这样,那么一个线程是否不可能输入Sum2Elements,在另一个线程进入InsertElement之前将标志更