保留订单的非阻止功能

时间:2015-07-30 17:02:09

标签: java multithreading concurrency threadpool nonblocking

我有以下方法:

void store(SomeObject o) {  

}  

此方法的想法是将o存储到永久存储,但该函数不应阻止。即我不能/不能在调用store的同一个线程中执行实际存储 我也不能启动一个线程并将该对象存储在另一个线程中,因为store可能被称为"巨大的"时间长,我不想开始产生线程 所以我选择哪些我不知道它们如何运作良好:
1)使用线程池(Executor系列)
2)在store中将对象存储在数组列表中并返回。当数组列表达到例如1000(随机数)然后开始另一个线程" flush"数组列表存储。但我仍然可能有太多线程的问题(线程池?)
因此,在这两种情况下,我唯一的要求就是我持久地存储对象的顺序与传递给store的顺序完全相同。使用多个线程混合起来。
怎么解决这个问题?
我怎样才能确保:
1)非阻塞store
2)准确的插入顺序
3)我不关心任何存储保证。如果是崩溃的东西我不在乎丢失数据,例如在存储之前缓存在数组列表中。

4 个答案:

答案 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