在一个接一个运行的2个线程之间添加延迟[关闭]

Posted

技术标签:

【中文标题】在一个接一个运行的2个线程之间添加延迟[关闭]【英文标题】:Adding delay in between 2 threads running one after another [closed] 【发布时间】: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 毫秒打印一个单词的两个实例 对这种任务使用观察者模式 【参考方案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 个睡眠的单线程循环) .

以上是关于在一个接一个运行的2个线程之间添加延迟[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

在没有 time.sleep 的代码中添加时间延迟(代码包含线程)

《java并发编程实战》读书笔记6--取消与关闭

可以同时运行 2 个 for 循环,一个接一个地循环吗?

c# 一个程序关闭,如果有前台线程还在运行,当前台线程运行完是不是会关闭?还是一直存在?

如何从 postDelayed 添加的处理程序对象中删除可运行对象?

dos下执行bat文件,如何让两个命令之间自动延迟3秒后再继续执行?