如何使用循环运行的线程来使用Thread.yield()?

时间:2012-03-07 17:57:08

标签: java multithreading timer

我有以下情况。我有一个主要在一个线程上运行的应用程序。它已经变大了,所以我想运行一个看门狗线程,只要主线程变成一个不同的代码/方法/类块,就会调用它,这样我就可以看到代码中有“运动”。如果监视程序被同一区域调用超过一秒钟或几分钟,它将设置一个易失性布尔值,主线程在下一个检查点读取并终止/重新启动。 现在的问题是让任何一个线程同时运行一些。一旦主线程运行,它就不会让看门狗定时器计数正确。因此,我每次调用看门狗时都会考虑屈服(因此可以计算时间并设置值),但无济于事。使用Thread.sleep(1)而不是Thread.yield()工作。但是我不希望有几个代码区域浪费计算时间,我确信我没有按照它的使用方式进行。

这是一个非常简单的示例,说明如何使用Thread.yield()。我不明白为什么这里的线程不会切换(它们会在“长时间”和很大程度上不可预测的时间之后切换)。请给我一个建议,告诉我如何使这个简单的例子输出ONE和TWO。就像之前写的一样,如果我用sleep(1)切换yield(),它就会像我需要它一样工作(尽管无意义地等待)。

    Runnable run1 = new Runnable(){
        public void run(){
            while(true){
                System.out.println("ONE");
                Thread.yield();
            }
        }
    };

    Runnable run2 = new Runnable(){
        public void run(){
            while(true){
                System.out.println("TWO");
                Thread.yield();
            }
        }
    };

    Thread tr1 = new Thread(run1);              
    Thread tr2 = new Thread(run2);

    tr1.start();
    tr2.start();

2 个答案:

答案 0 :(得分:10)

<强> Thread.yield()

  

这种静态方法主要用于通知系统   当前线程愿意“放弃CPU”一段时间。该   一般的想法是:

     

线程调度程序将选择要运行的其他线程而不是   现在的。

     

但是,线程如何实现让步的细节   调度程序因平台而异。一般来说,你不应该   依靠它以特定的方式行事。不同的事情包括:

     

在屈服之后,线程将有机会再次运行;   该线程是否放弃其剩余量。

外卖是这种行为几乎是可选的,无法确保实际做任何确定性的事情。

您要做的是序列化示例中两个线程的输出,同步您所述问题中的输出(这是一个不同的问题),以及这将需要某种锁或互斥锁来阻塞第二个线程,直到第一个线程完成,这种方式会破坏并发点,这通常是线程被使用的原因。

<强>解决方案

您真正想要的是标志状态的共享数据,第二个线程可以对第一个线程更改做出反应。优选地,事件驱动的消息传递模式将更容易以同时安全的方式实现。

第二个线程将由第一个线程和一个调用它的方法生成,以递增它所在块的计数器,你只需使用纯消息传递并传入状态标志Enum或一些其他状态变化的通知。

想要做的是进行任何类型的轮询。使它成为事件驱动,只让第二个线程始终运行,并检查由父线程设置的实例变量的状态。

答案 1 :(得分:0)

  

我不明白为什么这里的线程不会切换(它们在“长时间”和很大程度上不可预测的时间之后)。请给我一个建议,告诉我如何使这个简单的例子输出ONE和TWO。就像之前写的一样,如果我用sleep(1)切换yield(),它就会像我需要它一样工作(尽管无意义地等待)。

我认为这更多地是关于~1000 println次呼叫(当你使用sleep(1)时)和许多,更多没有睡眠时的差异。我认为Thread实际上正在屈服,但它可能是在多处理器盒上,所以产量实际上是无操作。

所以你所看到的仅仅是System.out的竞赛条件。如果您将结果运行一分钟并将结果发送到文件,我认为您会在输出中看到相似数量的"ONE""TWO"消息。即使您删除yield(),您也会看到此行为。

我刚用你的代码进行了快速试用,将输出发送到/tmp/xyield()程序运行5秒,生成1.9米/ 483k行,输出sort | uniq -c

243152 ONE
240409 TWO

这意味着每个线程的生成速度超过40,000行/秒。然后我删除了yield()语句,我得到了与你所期望的竞争条件不同的行数相同的结果 - 但是相同的数量级。