在一个接一个运行的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
块内,但这使得代码更优雅,而不是空的try
。 sleep()
必须在外面,以确保其他线程在该线程休眠时通过第一个锁进入。
这确保了如果线程 Ping 正在休眠,线程 Pong 会获取lock
,因此它将接下来进入synchronized
块。当 Ping 唤醒并走出synchronized
块时,即使恰好在 Pong 之前被调度,它也无法继续,因为它无法占用锁,并且必须等待 Pong 进入 synchronized
块并输出它的单词。
【讨论】:
[...] 同一个线程不会再次获得监视器。 我认为 java 会处理这个问题,因为第二个线程等待第一个释放监视器,然后在球被释放后立即抓住球。如果我错了,请纠正我 我认为没有任何保证,因为同步块结束时不能保证线程上下文切换。我也可能是错的......会检查。 @Lino 除了synchronized
不保证任何线程调度的公平性之外,还没有找到太多信息。如果一个线程碰巧比另一个线程具有更高的优先级,这可能会导致饥饿,而较低优先级的线程几乎没有任何 CPU 时间。我会说最好谨慎行事,并确保严格处理比赛条件。我添加了另一种方法。
无论如何感谢您的研究,顺便说一句,答案很好。如果可以的话,我会再次投票:)虽然我不太喜欢使用两种不同锁定机制的方式,但我想没有其他方法可以解决它。
好吧,ReentrantLock
是为这种情况添加的,在这种情况下,您不能重叠 2 个 synchronized
块。公平地说,这个问题有点奇怪,我认为将这些循环相互移交并不常见(您不妨将其作为具有 2 个睡眠的单线程循环) .以上是关于在一个接一个运行的2个线程之间添加延迟[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
在没有 time.sleep 的代码中添加时间延迟(代码包含线程)
c# 一个程序关闭,如果有前台线程还在运行,当前台线程运行完是不是会关闭?还是一直存在?