【问题标题】:Adding delay in between 2 threads running one after another [closed]在一个接一个运行的2个线程之间添加延迟[关闭]
【发布时间】:2019-08-23 16:41:18
【问题描述】:

我试图在 2 个线程之间放置 5 秒的间隔,在另一个线程之后运行一个,即假设我的第一个线程打印“X”,将会延迟 5 秒,然后另一个线程打印“Y”,再次打印 5秒延迟,然后是“X”,这会持续下去,说 30 次。

import java.lang.*;
import java.util.concurrent.TimeUnit;
class PingPong implements Runnable
{   String word;
    PingPong(String s){
     word = s;
    }

    public void run()
    {

    try

    {

         for(int  i = 0; i<30; i++)

          {
              System.out.println(word);
              Thread.sleep(100) ;
           }
    } catch (InterruptedException e)

     { e.printStackTrace(); }

   }
   public static void main(String[] args){

     Runnable p1 =  new PingPong("ping");

     Thread  t1 = new Thread(p1);

     t1.start();
     Runnable p2 = new PingPong("pong");

     Thread t2 = new Thread(p2);
     t2.start();
    }
 }

【问题讨论】:

  • 如果两个线程同时独立运行,您希望它们如何相互了解?
  • 请格式化您的问题,为什么要使用大写字母?你的尝试在哪里?我所看到的只是一个线程每 100 毫秒打印一个单词的两个实例
  • 对这种任务使用观察者模式

标签: java multithreading


【解决方案1】:

除非您引入某种同步机制,否则线程是相互独立的。因此,您需要做的第一件事是更改您的 PingPong 类以进行同步,每个线程都将等待。

我们称这个对象为ball。您可以在PingPong 的构造函数中传递它。它可以是您想要的任何对象(甚至只是 Object),也可以为它创建自己的小类。

然后在你的循环中,你可以这样做:

synchronized(ball) {
  System.out.println(word);
  Thread.sleep(5000);
}
Thread.sleep(1000);

这样每个线程将阻塞 5 秒,直到它允许另一个线程“占用”球的监视器并输出它的单词。

第二次休眠是任意的,但很重要,这样同一个线程就不会再次获得监视器。

一个稍微复杂但更正确的方法是使用第二个ReentrantLock。同样,您必须将它与之前的 ball 对象一起传递给构造函数。我们称之为lock

lock.lock();
synchronized(ball) {
  try {
    System.out.println(word);
  } finally {
    lock.unlock();
  }

  Thread.sleep(5000);
}

unlock() 位于finally 块中,以确保如果抛出任何异常,锁不会永远保持锁定状态。

System.out 实际上不需要在try 块内,但这使得代码更优雅,而不是空的trysleep() 必须在外面,以确保其他线程在该线程休眠时通过第一个锁进入。

这确保了如果线程 Ping 正在休眠,线程 Pong 会获取lock,因此它将接下来进入synchronized 块。当 Ping 唤醒并走出synchronized 块时,即使恰好在 Pong 之前被调度,它也无法继续,因为它无法占用锁,并且必须等待 Pong 进入 synchronized 块并输出它的单词。

【讨论】:

  • [...] 同一个线程不会再次获得监视器。 我认为 java 会处理这个问题,因为第二个线程等待第一个释放监视器,然后在球被释放后立即抓住球。如果我错了,请纠正我
  • 我认为没有任何保证,因为同步块结束时不能保证线程上下文切换。我也可能是错的......会检查。
  • @Lino 除了synchronized 不保证任何线程调度的公平性之外,还没有找到太多信息。如果一个线程碰巧比另一个线程具有更高的优先级,这可能会导致饥饿,而较低优先级的线程几乎没有任何 CPU 时间。我会说最好谨慎行事,并确保严格处理比赛条件。我添加了另一种方法。
  • 无论如何感谢您的研究,顺便说一句,答案很好。如果可以的话,我会再次投票:)虽然我不太喜欢使用两种不同锁定机制的方式,但我想没有其他方法可以解决它。
  • 好吧,ReentrantLock 是为这种情况添加的,在这种情况下,您不能重叠 2 个 synchronized 块。公平地说,这个问题有点奇怪,我认为将这些循环相互移交并不常见(您不妨将其作为具有 2 个睡眠的单线程循环) .
猜你喜欢
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 2015-06-15
  • 2011-06-01
  • 2021-03-18
相关资源
最近更新 更多