如果你曾经使用过p2p下载软件,他们可以下载一个带有多线程的文件,而且他们只创建了一个文件,所以我想知道线程如何将数据写入该文件。顺序还是并行?
想象一下,您想要将大型数据库表转储到文件中,以及如何更快地完成这项工作?
答案 0 :(得分:21)
您可以使用多个线程将a写入文件,例如一个日志文件。但是你必须像@Thilo指出的那样协调你的主题。您需要同步文件访问权限并且只写入整个记录/行,或者您需要有一个策略来将文件的区域分配给不同的线程,例如重新构建具有已知偏移和大小的文件。
由于性能原因很少这样做,因为大多数磁盘子系统在顺序写入时表现最佳,而磁盘IO是瓶颈。如果CPU创建记录或文本行(或网络IO)是它可以帮助的瓶颈。
要将大型数据库表转储到文件中的图像,以及如何更快地完成此工作?
顺序编写可能是最快的。
答案 1 :(得分:18)
Java nio包旨在允许这样做。请查看http://docs.oracle.com/javase/1.5.0/docs/api/java/nio/channels/FileChannel.html上的示例。
您可以将一个文件的多个区域映射到不同的缓冲区,每个缓冲区可以由一个单独的线程单独填充。
答案 2 :(得分:2)
同步声明可以实现此目的。尝试下面的代码,我在类似的上下文中使用。
package hrblib;
import java.io.*;
public class FileOp {
static int nStatsCount = 0;
static public String getContents(String sFileName) {
try {
BufferedReader oReader = new BufferedReader(new FileReader(sFileName));
String sLine, sContent = "";
while ((sLine=oReader.readLine()) != null) {
sContent += (sContent=="")?sLine: ("\r\n"+sLine);
}
oReader.close();
return sContent;
}
catch (IOException oException) {
throw new IllegalArgumentException("Invalid file path/File cannot be read: \n" + sFileName);
}
}
static public void setContents(String sFileName, String sContent) {
try {
File oFile = new File(sFileName);
if (!oFile.exists()) {
oFile.createNewFile();
}
if (oFile.canWrite()) {
BufferedWriter oWriter = new BufferedWriter(new FileWriter(sFileName));
oWriter.write (sContent);
oWriter.close();
}
}
catch (IOException oException) {
throw new IllegalArgumentException("Invalid folder path/File cannot be written: \n" + sFileName);
}
}
public static synchronized void appendContents(String sFileName, String sContent) {
try {
File oFile = new File(sFileName);
if (!oFile.exists()) {
oFile.createNewFile();
}
if (oFile.canWrite()) {
BufferedWriter oWriter = new BufferedWriter(new FileWriter(sFileName, true));
oWriter.write (sContent);
oWriter.close();
}
}
catch (IOException oException) {
throw new IllegalArgumentException("Error appending/File cannot be written: \n" + sFileName);
}
}
}
答案 3 :(得分:1)
这是什么类型的文件?为什么需要用更多线程来喂它?这取决于文件用法的特征(我不知道更好的词)。
通过网络从多个地方传输文件(简称:类似Torrent)
如果要传输现有文件,程序应该
将数据块附加到文件(简称:记录)
如果线程只是将固定或各种长度信息附加到文件,则应使用公共线程。它应该使用一个相对较大的写缓冲区,因此它可以快速服务客户端线程(只需要接受字符串),并将其清除出最佳调度和块大小。它应该使用专用磁盘甚至是计算机。
此外,可能存在一些性能问题,这就是为什么日志记录服务器,甚至是昂贵的商业服务器。
读写随机时间,随机位置(简称:数据库)
它需要复杂的设计,使用互斥体等,我从来没有做过这种事情,但我可以想象。向Oracle询问一些技巧:)
答案 4 :(得分:0)
您可以让多个线程写入同一个文件 - 但一次只能写一个。在写入文件之前,所有线程都需要进入同步块。
在P2P示例中 - 实现它的一种方法是找到文件的大小并创建该大小的空文件。每个线程都在下载文件的不同部分 - 当需要写入时,它们将进入同步块 - 使用搜索移动文件指针并写入缓冲区的内容。