我希望多次写入文件(100k +),并且写入将通过片状网络进行。所以要做到这一点,我正在考虑使用Java ExecutorService
来帮助生成线程,但我不确定哪种设置组合能够正确地实现以下功能:
我相信这可以通过执行程序功能以及主程序对象上的.wait()
和.notify()
命令的组合来完成。但是,我只是不确定如何精确地使用执行程序API来完成这项工作。
这是我得到的:
private void writeToFileInSeperateThread(final PrintWriter writer, final String text) {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
executor.submit(new Thread(new Runnable() {
public void run() {
writer.println(text);
}
})).get(5L, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
executor.shutdown();
}
在单个进程中,该方法将被调用100k +次,所以我不确定每次都应该创建一个新的ExcutorService
实例,还是使用相同的实例? (在我尝试使用同一个版本时,我不断获得我认为与.newSingleThreadExecutor()
指令相关的异常。
希望保持Java 5兼容,但Java 6还可以。在Windows XP / 7上运行。
更新: 这似乎已经在初始测试中完成了这个技巧:
private class WriterStringPair {
public final PrintWriter writer;
public final String text;
public WriterStringPair(PrintWriter writer, String text) {
this.writer = writer;
this.text = text;
}
}
private void writeTextInSeperateThread(Writer writer, String text) {
try {
textQueue.offer(new WriterStringPair(writer, text), 300L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
errOut.println(e);
e.printStackTrace();
}
}
final BlockingQueue<WriterStringPair> textQueue = new ArrayBlockingQueue<WriterStringPair>(500);
private void setWritingThread() {
new Thread((new Runnable() {
public void run() {
WriterStringPair q;
while (!shutdown && !Thread.currentThread().isInterrupted()) {
try {
q = textQueue.poll(1L, TimeUnit.SECONDS);
if (q != null) {
q.writer.write(q.text + "\n");
q.writer.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
})).start();
}
答案 0 :(得分:3)
如果不了解有关您通过“片状”网络撰写文件的更多详细信息以及具体方法,我们很难给出详细信息。但是这里有一些事情要考虑。
我会弄清楚有多少并发编写器在这里为您提供最佳性能 - 或者目标上最可靠的输出。然后你应该启动固定数量的这些编写器,每个编写器都来自共享的BlockingQueue
(如果重要的话,每个编写器一个队列)。您应该快速超过您的IO或网络带宽,因此从5个左右的作者开始,然后根据需要上下移动。
public void run() {
writer.println(text);
}
是的,你不想在每行工作方面做这类事情。最好将String text
放入BlockingQueue<String>
,然后让您的编写器Runnable
类在该队列中ExecutorService
出列,并且只在队列为空时停止或者设置了shutdown
布尔值。
正如Peter所提到的,你需要注意用排队的文本字符串填充内存。如果输入文字很大,您应该将BlockingQueue
的限制设置为几百左右。
我不确定每次都应该创建一个新的
ExecutorService
实例,还是使用相同的实例?
当然你应该有一个服务而不一遍又一遍地创建一个服务。
我相信这可以通过执行器功能以及主程序对象上的.wait()和.notify()命令的组合来完成。
如果写得正确,则不需要使用wait和notify。我有一个volatile boolean shutdown = false
所有作家都在观看。它们中的每一个都使用查看关闭从文本队列中出列。类似的东西:
while (!shutdown && !Thread.currentThread().isInterrupgted()) {
String text = textQueue.poll(1, TimeUnit.SECONDS);
if (text != null) {
// write the text
}
}
如果写入失败或者您可以重试它或其他任何必要的东西。
答案 1 :(得分:2)
一些问题
我建议将数据保存到本地系统(如JMS或数据库或文件(例如Java-Chronicle)),并在可用时将数据复制到NFS。
假设您无法修复NFS,因此它不会出现问题。