2012-12-22 22 views
1

我正在使用信号量来强制在我的程序中执行一些命令:我有一个主线程和一些在主线程中创建的子线程。 在每个步骤的主线程中打勾了一个时钟,之后我希望每个子线程一个接一个地运行。子线程的顺序并不重要,但我希望它们都在每一步中运行(并且每一步中只运行一次)。 我已经写过这段代码,但问题是,在某些情况下,在一些子线程上运行几次而不让别人有机会运行?!如何在java中的信号量中强制排序

主线:

 Semaphore okToTick = new Semaphore(3); 
    Semaphore okToWork = new Semaphore(0, true); 

    int i = 0; 

    new TestClass2(0, okToTick, okToWork); 
    new TestClass2(1, okToTick, okToWork); 
    new TestClass2(2, okToTick, okToWork); 

    while(true){ 

     okToTick.acquire(3); 

     System.out.printf("\clock : %s\n", i++); 


     okToWork.release(3); 

    } 

和子线程的run():

semaphores here, passed by cnstr() 
    ID = //passed in by cnstr()  
    isBusy = false; 
    ---------------------------------- 
    try{ 
     while(true){ 

      okToWork.acquire(); 

      if(!isBusy){ 
       System.out.println("inside sub " + ID); 
       isBusy = true; 
      } 


      okToTick.release(); 

     } 

    } 
    catch(Exception e){} 

我想这样的结果:

clock : 0 
    inside sub 1 
    inside sub 0 
    inside sub 2 

    clock : 1 

    clock : 2 
    ... 

但有时我得到这个:

clock : 0 
    inside sub 1 

    clock : 1 
    inside sub 0 
    inside sub 2 

    clock : 2 
    ... 
+0

提示:当您释放okToTick时,时钟可能会打勾。而且,由于您在打印后立即发布,时钟有时会立刻出现并不奇怪。您需要等待所有子线程完成后再说可以打勾。祝你的作业好运。 – Hjalmar

+0

如果您有要按特定顺序执行的任务,则应该在同一个线程中执行全部任务。如果您有多个可以按任意顺序执行的独立任务,则多个线程很有用。 –

回答

6

我认为你正在寻找一个CyclicBarrier

一个同步辅助类,它允许一组线程都等待对方达成一个共同的障碍点。 CyclicBarriers在涉及固定大小的线程的程序中很有用,它必须偶尔等待对方。该屏障称为循环,因为它可以在等待线程释放之后重新使用。

+0

我不熟悉这个话题。是否可以仅使用信号量来完成这项工作? – msn

+5

您正在使用锤子来驱动螺丝。你为什么不学习如何使用螺丝刀。这是记录,我甚至链接到javadoc。点击,阅读,理解并尝试一些东西。如果你只想使用信号量,我会在每个工作线程中使用一个信号量。 –

+0

你是对的,但我必须在明天之前完成。正如我理解使用CyclicBarrier你必须使用一个实现可运行的类,但我不得不使用Thread的run方法。你能告诉我关于如何使用信号量来实现这个吗?每个工作线程使用一个信号量意味着什么? – msn

0

问题是您的“子线程”可能从信号量获取多个许可证,并且您没有在输出中实现它,因为“内部子”输出只会打印一次(您会多次看到它,如果你删除围绕它的if(!isBusy))。如果您不希望每个“子线程”获取多个许可证,请删除外部的while(true)循环。

okToWork.acquire(); 

    //if(!isBusy){ Removed to show when this sub-thread is actually acquiring permits 
     System.out.println("inside sub " + ID); 
    // isBusy = true; 
    //} 


    okToWork.release(); 
+0

谢谢你的回复。即使我仍然存在这个问题,我也会删除它。在某些情况下,一个线程在一个tick中运行几次!我必须在子线程中有循环。这只是程序的一部分。线程应该运行在一个循环中。 – msn

1

在你的情况下,一个线程可以获取okToWork和其他人之前释放okToTick多次,甚至有机会旋转起来,即得。线程号1可以做到最多3次okTowork.acquire() - >okToTick.release()之前。

您还为每个线程打印inside sub x一次,因为您永远不会重置isBusy标志。

您需要区分它们,使用Semaphore的最简单方法是为每个线程提供不同的okToTick Semaphore