2011-02-28 60 views
1

我在写一个简单的线程应用程序。线程只是一个消息消费者并对其进行处理。但是,如果线程以某种方式被打断并且消息没有完全处理,我想把它放回队列并让其他实例获取它。因此,我不得不像这样的代码:在运行()的同步块的中间是否可以中断线程?

public void run() 
{ 
    Map<String, String> data = null; 
    try 
    { 
     while(true) 
     { 
      data = q.getData(); 
      System.out.println(this+" Processing data: "+data); 
      // let others process some data :) 
      synchronized(this){ 
       sendEmail(data); 
       data = null; 
      } 
     } 
    } 
    catch (InterruptedException e) 
    { 
     System.out.println(this+" thread is shuting down..."); 
     if(null!=data) 
      q.add(data); 
    } 

} 

谢谢...

编辑:感谢您的答复。现在一切都很清楚。我明白,即使代码行在同步块中,如果它们中的任何一个都可以抛出InterruptedException,那么它只是意味着它们可以在此时被中断。 q.getData()行将此线程置于'阻塞'状态(我在q.getData()中使用LinkedBlockedQueue)。那时,这个线程可以被中断。

+0

这是坏的...我做了一个快速测试,我可以在同步块中间中断线程......坏的不好...... – demotics2002 2011-02-28 08:09:27

+0

为什么在这种情况下需要'synchronized'? – axtavt 2011-02-28 08:23:43

+0

我想将sendMail()和设置为null为原子。 – demotics2002 2011-02-28 08:29:03

回答

4

除了大卫·哈克尼斯的回答:你也不明白​​关键字的含义。

Synchornized不是一种“原子”或“不可中断”块。

除了其他线程不能同时在同一个对象上输入同步块(在你的情况下为this)(+某些内存一致性保证与你的情况无关),同步块不能提供任何保证。

因此你的情况的synchornized使用是没有意义的,因为没有必要保护data从其他线程(也,你是同步的this的并发访问,我不认为其他线程将同一对象上同步)。

参见:

+0

感谢您的光。我现在明白了。 – demotics2002 2011-02-28 08:50:39

0

Java同步是指当一个线程已经收购了它没有其他的线程可以访问相同的锁。

如果您不希望任何其他线程能够访问消息(或任何其他对象),请使用synchronized(message)块。

+0

'是'部分是正确的。但奇怪的是我的另一个线程在同步块内部时能够中断这个线程。 – demotics2002 2011-02-28 08:26:51

+0

在你的代码中,你使用'synchronized(this){}'来获取线程上的锁。你想要的是锁定消息,所以你需要使用'synchronized(data){}' – 2011-02-28 08:57:19

6

其他线程在其上调用interrupt()时线程不会捕获InterruptedException,也不会奇迹般地停止它的任何操作。相反,该方法设置一个标志,线程可以使用interrupted()读取。如果设置了某些其他方法,则会检查此标志并提高InterruptedException。例如,Thread.sleep()和许多等待外部资源的I/O操作都会抛出它。

查看Java Thread Interrupts Tutorial了解更多信息。

+0

我不明白。我有另一个线程(仅用于测试),可以在sendMail()和data = null中间中断此线程,这些线程位于同步块中。 – demotics2002 2011-02-28 08:32:43

+0

@demotics - 哦,我明白了。你认为'synchronized'可以让你的线程保持JVM的全部注意力,而无需安排任何其他线程运行(你称之为中断)。正如axtavt指出的那样,这不是'synchronized'所做的事情,也不是线程中断的意思。 – 2011-02-28 22:13:16

+0

谢谢大卫。我最初并不了解你的观点。但现在很清楚。你的回答很大程度上帮助我意识到我对线程的理解太缺乏。 – demotics2002 2011-03-01 01:42:05

1

忽略该while(true)使线程进入一个CPU循环的那一刻...

如果sendMail做任何检查线程中断它会抛出一个中断的异常。所以你的问题的答案可能是坚实的,线程可以在同步块内被中断,你将不得不捕捉异常并检查。

这就是说,InterruptedException是一个检查异常,所以缺少有趣的bugger在较低级别完成,sendMail应该指出它可以抛出InterruptedException。