我有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