2013-02-16 67 views
0

我有一個FileScanner線程在列表中添加新文件,並且多個FileParser線程獲取新文件並分別解析自己的文件。爲了同步起見,我在列表中添加了列表並從列表中讀取同步資源塊。問題是,有時FileScanner線程似乎餓死,並且不會進入等待其他FileParser線程釋放資源(列表)的同步塊。 我的問題是,如果我將FileScanner的最大優先級設置爲最小值,將其他FileParser線程的最小值設置爲最小值,它是否可以解決問題? 換句話說,線程優先級是否會影響JVM在線程之間進行選擇以授予對同步塊的訪問權限? 謝謝。線程優先級是否影響同步塊訪問?

UPDATE:

private List<ScannerFile> scannedFiles = Collections.synchronizedList(new LinkedList<ScannerFile>()) ; 

這就是所謂的在我的FileScanner螺紋:

synchronized(scannedFiles){ 
     for(ScannerFile f: newList) 
      try{ 
       scannedFiles.add(f); 
      } 
      catch(ConcurrentModificationException e){ 
       logger.error(e); 
      } 
    } 

,這是叫我FileParser線程:

synchronized(scannedFiles){ 
    try{ 
     for(ScannerFile f: scannedFiles){ 
      if(parserName.equals(f.getParserName()) && f.isNew() == true){ 
       listNewFiles.add(f); 
      }   
     } 
     return listNewFiles; 
    } 
    catch(ConcurrentModificationException e){ 
     logger.trace(e); 
     return new ArrayList<ScannerFile>(); 
    } 
} 
+2

使用,而不是同步的一個併發收集會減少爭。 – assylias 2013-02-16 11:07:41

+0

我在http://tutorials.jenkov.com/java-concurrency/starvation-and-fairness.html中找到了解決方案 – 2013-02-19 10:43:28

+0

不知道您在那找到了什麼。這個人似乎試圖重新實現一個已存在於java.util.concurrent包中的鎖。我不認爲這樣做的目的是誠實的(除非你想引入微妙的錯誤)。 – assylias 2013-02-19 10:57:45

回答

1

線程優先級是一個提示或意見,這可能會或可能不會產生影響。因此,依靠併發程序的正確性的優先級設置是危險的。

從「Java併發實踐」(Goetz等人):

,因此要避免使用線程的優先級,因爲它們可以增加平臺的依賴,會導致活躍度的問題[...]

如果您的程序遇到死鎖,則併發邏輯會出現問題。改變線程優先級會(不太可能是最好的情況下)掩蓋該問題或(在可能的情況下)引入未確定的硬件特定行爲。

你的問題的描述,看起來像ReadWriteLock的主要例子。但是,如果沒有一個簡明的代碼示例,很難給出合理的建議。

+0

@Pyanja我添加了一些代碼片段,希望它會有所幫助。謝謝 – 2013-02-16 11:16:23

1

線程優先級不應該打開或打破同步。聽起來像是阻塞收集中的一個問題,無論如何您都不應該實施自己的收集。看一下LinkendBlockingQueue和java.util.concurrent中的朋友。

+0

感謝您的回覆,但它不是關於製作或破壞同步。當一個線程在一個同步塊中時,其他線程將一直等到該塊內的線程退出,然後等待,但它們不會排隊。我的意思是下一個要輸入的線程不是由FIFO算法選擇的。我的意思是像隨機或其他東西。我想知道優先事項是否對此事有影響。 – 2013-02-18 13:54:37

+1

對於併發包中的鎖類,您可以選擇使它們*公平*,效率很低。您無法使用同步塊進行此操作。如果沒有公平性,下一個線程的選擇是由OS決定的,在這個OS中,優先級影響,但確定調度。 – 2013-02-18 14:01:14

+0

Thanks @Ralf H,我會檢查併發包是否公平。 – 2013-02-19 10:30:50

0

存在邏輯錯誤。這應該工作(我沒有一個IDE再次確認):

LinkedBlockingQueue<ScannerFile> newList = new LinkedBlockingQueue<>(); 
LinkedBlockingQueue<ScannerFile> scannedFiles = new LinkedBlockingQueue<>(); 
for(;;){ 

try{ 
ScannerFile f = newList.get(); 
scannedFiles.add(f); 
} 
catch(InterruptedException ex{ 
Thread.currentThread.interrupt(); 
//log 
break; 
} 
} 

ThreadParser會是這樣的:

for(;;){ 
try{ 
ScannedFile f= scannedFiles.get(); 
//other logic goes here 
}catch(InterruptedException ex{ 
Thread.currentThread.interrupt(); 
//log 
break; 
} 
} 
+0

感謝您的詳細回答,但我認爲您誤解了這個問題。我的程序邏輯很好,整個程序在任何時候都能正常工作99%。在一週內只有一次,但InputScanner線程不檢測任何文件,但其他線程目前正在工作。我知道這一切,因爲我記錄了每一步。無論如何,我的問題是一個普遍的問題,我只是包含了明確的代碼。 – 2013-02-18 13:48:35