java - 保持顺序的非阻塞函数

标签 java multithreading concurrency threadpool nonblocking

我有以下方法:

void store(SomeObject o) {  

}  

此方法的想法是将o 存储到永久存储 函数不应阻塞。 IE。我不能/不能在调用 store 的同一个线程中进行实际存储。
我也不能启动一个线程并从另一个线程存储对象,因为 store 可能被称为“大量”次数,我不想开始生成线程。
所以我选择了我看不到它们如何运作良好的选项:
1)使用线程池(Executor家族)
2) In store 将对象存储在数组列表中并返回。当数组列表到达例如1000(随机数)然后启动另一个线程以将数组列表“刷新”到存储中。但是我仍然可能会遇到线程过多的问题(线程池?)
因此,在这两种情况下,我唯一的要求就是按照传递给 store 的完全相同的顺序持久存储对象。使用多线程会把事情搞混。
如何解决?
我如何确保:
1) 非阻塞store
2) 准确的插入顺序
3)我不关心任何存储保证。如果例如有些东西崩溃了,我不在乎丢失数据,例如在存储它们之前缓存在数组列表中。

最佳答案

我会使用 SingleThreadExecutor 和 BlockingQueue。

SingleThreadExecutor,顾名思义,只有一个线程。使用它从队列中轮询并持久化对象,如果为空则阻塞。

您可以在存储方法中向队列添加不阻塞。

编辑 实际上,您甚至不需要那个额外的队列 - JavaDoc of newSingleThreadExecutor说:

Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.

所以我认为这正是您所需要的。

private final ExecutorService persistor = Executors.newSingleThreadExecutor();
public void store( final SomeObject o ){
    persistor.submit( new Runnable(){
            @Override public void run(){
                // your persist-code here.
            }
        } );
}

使用具有准无限循环和使用额外队列的 Runnable 的优点是可以编写一些“突发”功能。例如,您可以让它等待只有在队列中有 10 个元素或最旧的元素至少在 1 分钟前添加时才保留...

关于java - 保持顺序的非阻塞函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31729872/

相关文章:

java - 使用 hibernate 删除对象后刷新 Jtable?

java - Eclipse 无法解析 Spring 3 mvc 模式

Python 使用 subprocess.Popen 关闭所有线程或进程

go - 中断当前的尾部并开始新的尾部

java - 无法在 Android App 中实例化类

c# - 创建 ThreadLocal EF 上下文

c# - 线程 - 如何通过 UI 交互终止工作/后台线程

java - 从 List<CompletableFuture> 转换为 CompletableFuture<List>

c# - 使用 IEnumerable 接口(interface)是否可以减少并发问题

java - 如何正确使用 getDayOfWeek 方法