我有以下方法:
void store(SomeObject o) {
}
此方法的想法是将o
存储到永久存储,但该函数不应阻止。即我不能/不能在调用store
的同一个线程中执行实际存储
我也不能启动一个线程并将该对象存储在另一个线程中,因为store
可能被称为"巨大的"时间长,我不想开始产生线程
所以我选择哪些我不知道它们如何运作良好:
1)使用线程池(Executor
系列)
2)在store
中将对象存储在数组列表中并返回。当数组列表达到例如1000(随机数)然后开始另一个线程" flush"数组列表存储。但我仍然可能有太多线程的问题(线程池?)
因此,在这两种情况下,我唯一的要求就是我持久地存储对象的顺序与传递给store
的顺序完全相同。使用多个线程混合起来。
怎么解决这个问题?
我怎样才能确保:
1)非阻塞store
2)准确的插入顺序
3)我不关心任何存储保证。如果是崩溃的东西我不在乎丢失数据,例如在存储之前缓存在数组列表中。
答案 0 :(得分:2)
我会使用SingleThreadExecutor和BlockingQueue。
SingleThreadExecutor作为名称sais有一个单独的Thread。使用它从队列中轮询并持久保存对象,如果为空则阻止。
您可以在商店方法中为队列添加非阻止功能。
修改强> 实际上,你甚至不需要额外的队列 - JavaDoc of newSingleThreadExecutor sais:
创建一个Executor,它使用单一工作线程在无界队列下运行。 (但请注意,如果此单个线程由于在关闭之前执行期间的故障而终止,则在需要执行后续任务时将使用新的线程。)保证任务按顺序执行,并且不会有多个任务处于活动状态在任何给定的时间。与其他等效的newFixedThreadPool(1)不同,保证返回的执行程序不可重新配置以使用其他线程。
所以我认为这正是你所需要的。
var Url = require('url');
var Path = require('path');
var url = 'http://i.imgur.com/Mvv4bx8.jpg?querystring=true';
var result = Path.extname(Url.parse(url).pathname); // '.jpg'
使用具有准无限循环和使用额外队列的Runnable的优点是可以编写一些“Burst”功能。例如,只有当10个元素在队列中或者至少在1分钟前添加了最旧的元素时,你才可以等待它继续...
答案 1 :(得分:1)
有一个单独的线程从队列末尾获取项目(阻塞空队列),并将它们写入磁盘。您的主线程store()
函数只是将项添加到队列的开头。
这里有一个粗略的想法(虽然我认为在生产代码中有更简洁或更快的方法,取决于你需要的速度):
import java.util.*;
import java.io.*;
import java.util.concurrent.*;
class ObjectWriter implements Runnable {
private final Object END = new Object();
BlockingQueue<Object> queue = new LinkedBlockingQueue();
public void store(Object o) throws InterruptedException {
queue.put(o);
}
public ObjectWriter() {
new Thread(this).start();
}
public void close() throws InterruptedException {
queue.put(END);
}
public void run() {
while (true) {
try {
Object o = queue.take();
if (o == END) {
// close output file.
return;
}
System.out.println(o.toString()); // serialize as appropriate
} catch (InterruptedException e) {
}
}
}
}
public class Test {
public static void main(String[] args) throws Exception {
ObjectWriter w = new ObjectWriter();
w.store("hello");
w.store("world");
w.close();
}
}
答案 2 :(得分:1)
我建议使用Chronicle-Queue这是我设计的库。
它允许您在不阻塞的情况下写入当前线程。它最初是为低延迟交易系统而设计的。对于小消息,写入消息大约需要300 ns。
您不需要使用背景线程或堆上队列,并且它不会等待数据默认写入磁盘。它还确保所有读者的订单一致。如果程序在您致电finish()
后随时死亡,则该消息不会丢失。 (除非操作系统崩溃/断电)它还支持复制以避免数据丢失。
答案 3 :(得分:0)
你的问题中的评论让你觉得你对多线程并不陌生,但它真的不那么难。
您只需要另一个负责写入存储的线程,该存储从队列中选择项目。 - 您的<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="jspdf.debug.js"></script>
<style type="text/css">
</style>
<script type="text/javascript">
function demoLandscape() {
var doc = new jsPDF('landscape');
doc.text(10, 10, 'Hello landscape world!\nThis is client-side Javascript, pumping out a PDF.');
// Save the PDF
doc.save('Test.pdf');
}
function demoHTML() {
var pdf = new jsPDF('p', 'pt', 'portrait');
source = '<html><body><p>test HTML string</p></body></html>'
margins = {
top : 80,
bottom : 60,
left : 60,
width : 522
};
// all coords and widths are in jsPDF instance's declared units
// 'inches' in this case
pdf.fromHTML(source, // HTML string or DOM elem ref.
margins.left, // x coord
margins.top, { // y coord
'width' : margins.width, // max width of content on PDF
},
function(dispose) {
// dispose: object with X, Y of the last line add to the PDF
// this allow the insertion of new lines after html
pdf.save('fileNameOfGeneretedPdf.pdf');
}, margins);
});
});
}
</script>
</head>
<body>
<input type="button" value="test2" onclick="demoHTML()">
</body>
</html>
函数只是将对象添加到内存中队列中并继续使用它。
一些假的代码:
store