[英]Threads occasionally blocking while writing to the same file
我試圖使用兩個單獨的線程從兩個文本文件(具有相同的行數,即10000)中讀取文件,一個文件包含字符串,另一個文件包含整數。 之后,我想從結果集中的相應位置寫入另一個文本文件(String,Integer)值,每個位置在不同的行上。 為此,我使用兩個實現Runnable接口的類。
我面臨的問題是,每次運行程序時,線程之一都有可能阻塞執行,並且我不明白為什么要考慮在一個線程中使用wait()和notify() synchronized
塊。 更具體地說,有時程序會成功運行以完成執行過程,而在大多數情況下,它會在各個階段停止(例如,在寫入的10000行中大約有3000條記錄,甚至有500條記錄)。
citireInteger是對另一個讀取Integer文件的線程的引用。
這是分別處理從String和Integer文件讀取的類中的相關代碼:
@Override
public void run(){
........
try {
pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));
for(int i = 0; i < strings.size(); i++){
synchronized(this){
pw.write(strings.get(i));
}
synchronized(citireInteger){
citireInteger.notifyAll();
}
try{
synchronized(this){
wait();
}
} catch(InterruptedException e){
e.printStackTrace();
}
}
} catch(FileNotFoundException e){
e.printStackTrace();
} catch(IOException e){
e.printStackTrace();
} finally{
pw.close();
}
synchronized(citireInteger){
citireInteger.notify();
}
}
讀取Integer文件的線程:
public void run(){
...........
try{
pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));
for(int i = 0; i < ints.size(); i++){
synchronized(this){
pw.write(ints.get(i) + '\n');
System.out.println(ints.get(i));
}
synchronized(citireString){
citireString.notifyAll();
}
try{
synchronized(this){
wait();
}
} catch(InterruptedException e){
e.printStackTrace();
}
}
} catch(FileNotFoundException e){
e.printStackTrace();
} catch(IOException e){
e.printStackTrace();
} finally{
pw.close();
}
synchronized(citireString){
citireString.notify();
}
}
發生的情況是,一個線程正在另一線程上調用notifyAll
,然后在與自己的編寫器同步以調用wait
之前被切換出去。 另一個線程進行寫操作,在其寫程序上進行同步,然后調用wait
。 然后,第一個線程再次進入,在其編寫器上同步,並調用wait
。 有你的僵局。
最好讓兩個線程在同一個對象上進行同步寫入。 最好將數據以線程安全的方式存儲在內存中,並在從兩個線程讀取完成后從單個線程寫入數據。
當您通知另一個線程時,另一個線程將僅在其他線程正在等待時看到它。 如果另一個線程在該同步塊之外,則在收到通知后進入該同步塊,然后它將等待一個通知,該通知不會發生,或者寧可發生,也不會在它開始等待之前發生。 很難真正確定此練習的目標是什么,但是我猜想這是兩個線程輪流執行寫操作的原因。 好的,那么,如何使synced(citireInt / String)塊包含整個代碼! 這樣,試圖獲得鎖的另一個線程將僅在另一個線程正在等待時才獲得該鎖。 我認為這不會保證任何阻塞,結果是兩個線程都一一輪換。
編輯:完全不像我描述的那樣,但是要點是同步的地方...
public void run()
{
...........
try
{
pw = new PrintWriter(new BufferedWriter(new FileWriter("rezultat.txt", true)));
synchronized(this)
{
for(int i = 0; i < ints.size(); i++)
{
pw.write(ints.get(i) + '\n');
System.out.println(ints.get(i));
synchronized (citireString)
{
citireString.notifyAll();
}
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
catch (Throwable e)
{
e.printStackTrace();
}
finally
{
pw.close();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.