2011-03-10 154 views
3

美好的一天! 我得到了有关在java中同步线程的问题。我正在开发创建计时器的程序,并允许重置它,删除和停止。只是为了学习如何使用线程。在java中同步线程

问题是代码只能同步一段时间......我无法理解我的错误。也许我的方式是错误的,所以我想知道如何解决这个问题。

我有下面的代码:

public class StopWatch 
{ 
    //Create and start our timer 
    public synchronized void startClock(final int id) 
    {         
      //Creating new thread. 
      thisThread = new Thread() 
      { 
       @Override 
       public void run() 
       { 
        try 
        {            
         while(true) 
         { 
          System.out.printf("Thread [%d] = %d\n", id, timerTime); 
          timerTime += DELAY;          //Count 100 ms 
          Thread.sleep(DELAY);          
         } 
        } 
        catch(InterruptedException ex) 
        { 
         ex.printStackTrace(); 
        } 
       } 
      }; 

      thisThread.start();   
    } 

… 
    //Starting value of timer 
    private long timerTime = 0; 
    //Number of ms to add and sleep          
    private static final int DELAY = 100;         

    private Thread thisThread; 
} 

我调用这个类,如:“?只给你同步一段时间”

StopWatch s = new StopWatch(1); 
      s.startClock(); 
StopWatch s2 = new StopWatch(2); 
      s2.startClock(); 
+3

我想你不理解什么“同步”意味着与线程编程有关。它跟时间没有任何关系。 – 2011-03-10 19:00:36

+0

@布莱恩罗奇 是的,你是对的。我在这里学习很多东西。 – ExiRe 2011-03-10 19:17:31

回答

7

我想你可能误解了“同步”。

这并不意味着线程在完全同步的时间内运行 - 而是一次只允许一个线程执行同步的代码块。在你的情况“同步”没有什么区别,因为你是从同一个线程调用startClock方法... ...

一般来说,Java(甚至是大多数高级语言)不可能保证两个线程因为它们总是容易被OS调度程序或JVM垃圾收集暂停等延迟,所以即使您有多个内核,也能在完全相同的时钟时间执行操作。

此外,Thread.sleep(...)不可靠作为计时机制,因为它睡觉的时间只是近似的。你受线程调度程序的支配。

建议解决方案:

使用System.currentTimeMillis()如果你想有一个线程独立定时mechansim。

+0

这是否意味着如果我会在同一时间启动2个定时器(使用线程),然后我会在同一时间停止它们,我不能保证相同的值?我理解对吗? – ExiRe 2011-03-10 19:08:13

+0

正确。线程睡眠不是一个准确的时间机制。如果您想要一致的计时器值,请使用System.currentTimeMillis()或类似的。 – mikera 2011-03-10 19:10:31

+0

我从他所描述的内容中搜集了什么,并且synchronized关键字没有提供。即使因为他使用同步关键字,其他所有内容都是平等的,他们也永远不会在同一时间运行,并始终关闭。 – 2011-03-10 19:18:31

2

你这是什么意思是你在这里同步的唯一的东西是startClock方法,它只是意味着两个线程不会同时在该方法内(并且看起来你不会这么做)。例如,如果您想同步对timerTime的访问,则需要在递增的timerTime周围的线程运行方法内部放置一个同步块(或者您可以使用AtomicLong)。

0

您应该重新阅读“同步”关键字的文档。我很确定在这种情况下,它所要做的就是让StartClock()的两个调用同时执行,这不会发生在给定代码的情况下,因为它们是从一个线程中一个接一个地调用的。一旦计时器线程开始,如果这是您的目标,则没有任何事情可以保持它们的同步。

0

您的第一个问题是,这是一个仅基于时间的解决方案。这很糟糕,因为程序无法控制执行所花费的时间。某些操作比其他操作需要更多时间,并且流程中的每个线程都不会同时执行。一般情况下,除非可以保证其他部分相同,否则不会同步任何内容。 。 。

阅读http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Semaphore.html,你也可以做

的Thread.join();在继续执行之前让主循环等待子线程的执行完成。

0

我想你误解了同步的意思。同步是为了确保多个线程对某个代码块的访问权限有限,这样您就不会在两个线程之间发生冲突。

我想你可能更感兴趣的是CyclicBarrier或CountDownLatch。两者都可以用于“同步”(在这种情况下,重载使用)多线程,以便他们尝试同时开始做事。

但是,请注意,不可能让多个线程在正好同时处理事情。你只能试着鼓励大约在同一时间去做。其余部分受系统内核操作系统调度影响。如果你有一个核心,他们将永远不会同时运行。