我有20個線程使用println()函數在名爲results.txt的文件上寫入。我如何同步它們?從多個線程寫入文本文件?
我注意到每次我的程序運行時,我在results.txt中都有不同數量的文本行。
謝謝。
我有20個線程使用println()函數在名爲results.txt的文件上寫入。我如何同步它們?從多個線程寫入文本文件?
我注意到每次我的程序運行時,我在results.txt中都有不同數量的文本行。
謝謝。
通過包含synchronized method的類訪問文件以寫入文件。一次只有一個線程將能夠執行該方法。
我認爲Singleton模式會適合您的問題:
package com.test.singleton;
public class Singleton {
private static final Singleton inst= new Singleton();
private Singleton() {
super();
}
public synchronized void writeToFile(String str) {
// Do whatever
}
public Singleton getInstance() {
return inst;
}
}
每當你需要編寫你的文件的時候,你只將不得不撥打:
Singleton.getInstance().writeToFile("Hello!!");
+1簡單但有效。然而,「a * class *」應該是「an * object *」(由具有所述同步方法的類實例化),因爲'synchronized'方法只是相互排斥的每個對象。 – 2012-04-05 10:47:30
所以我必須編寫一個「I/O」類,並在代碼中調用它來打印對象? – 2012-04-05 10:48:59
@MarcoMicheli這個答案的關鍵點是:['synchronized'](http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html) – 2012-04-05 10:49:30
使用日誌框架如具有所有已經解決的logback。
您打算將數據寫入一個文件。所以如果你試圖鎖定整個文件,最好使用一個線程來完成這項工作。雖然你產生了20個線程,但每次調用方法時只有其中一個線程正在運行,其他線程只是在等待鎖定。
我建議您使用RandomAccessFile
將數據寫入文件。然後每個線程都可以將一些獨特的數據寫入文件而不鎖定整個文件。
一些演示代碼如下
try {
final RandomAccessFile file = new RandomAccessFile("/path/to/your/result.txt", "rw");
final int numberOfThread = 20;
final int bufferSize = 512;
ExecutorService pool = Executors.newFixedThreadPool(numberOfThread);
final AtomicInteger byteCounter = new AtomicInteger(0);
final byte[] yourText = "Your data".getBytes();
for (int i = 0; i < yourText.length; i++) {
pool.submit(new Runnable() {
@Override
public void run() {
int start = byteCounter.getAndAdd(bufferSize);
int chunkSize = bufferSize;
if (start + bufferSize > yourText.length) {
chunkSize = yourText.length - start;
}
byte[] chunkData = new byte[chunkSize];
System.arraycopy(yourText, start, chunkData, 0, chunkSize);
try {
file.write(chunkData);
} catch (IOException e) {
//exception handle
}
}
});
}
file.close();
} catch (Exception e) {
//clean up
}
重複的問題......複製答案。 As I said here:
如果你可以拿着你的文件作爲FileOutputStream
你可以這樣鎖定:
FileOutputStream file = ...
....
// Thread safe version.
void write(byte[] bytes) {
try {
boolean written = false;
do {
try {
// Lock it!
FileLock lock = file.getChannel().lock();
try {
// Write the bytes.
file.write(bytes);
written = true;
} finally {
// Release the lock.
lock.release();
}
} catch (OverlappingFileLockException ofle) {
try {
// Wait a bit
Thread.sleep(0);
} catch (InterruptedException ex) {
throw new InterruptedIOException ("Interrupted waiting for a file lock.");
}
}
} while (!written);
} catch (IOException ex) {
log.warn("Failed to lock " + fileName, ex);
}
}
來自FileLock的JavaDoc: 「代表整個Java虛擬機保留文件鎖定,它們不適用於控制同一虛擬機中多個線程對文件的訪問。 – theadam 2013-07-26 08:19:30
@theadam - 緊隨其後的是*文件鎖對象可安全地用於多個併發線程。* - 只是說 – OldCurmudgeon 2013-07-26 08:35:54
多個線程可以安全地使用獲得的FileLock對象,但是此鎖不適用於控制多線程對文件的訪問。那就是 - 對象(FileLock)本身是線程安全的。不應該像你描述的那樣使用它。 – theadam 2013-07-27 09:08:04
只是想知道,你得到了同樣的作業嗎? http://stackoverflow.com/questions/9972549/threads-and-file-writing – 2012-04-05 11:10:03
20個線程.. 20個線程..有什麼機會? – 2012-04-05 12:01:53
不同行數..不同行數.. – 2012-04-05 12:03:31