我一直在考虑在Java中实现异步处理的不同方法。我想到了一些可能性,想要了解一些是否比其他更好,并且可能会就如何做到这一点得到进一步的建议。最常见的用例是使用以下API void sendData(Data data)
甚至void sendData(Data data, Handler handler)
通过连接(例如TCP)发送数据包。以下是我的一些想法:
是否有更好的使用方法,或者如果您有任何其他一般性想法,请分享您的意见。
答案 0 :(得分:1)
你的大部分建议实际上是不同的方式来打扮同样的东西。
在幕后,执行程序服务具有一个或多个后台线程池,用于排队。请求将提交给它。
1和2都是说“排队要做的事情,有一个处理它的线程”的方式
所以基本上1和2都是彼此的变体。它们也是3的子集。
对于4.我不确定你的意思在这里?
ExecutorService
旨在完成你想要做的事情 - 如果你有多个线程来执行任务,那么显然就是这样做的。
如果你只有一个线程,你仍然可以使用ExecutorService
,但选择不太明确。使用一个线程和一个BlockingQueue
是相当简单的,这样可能就是这样。
答案 1 :(得分:0)
我总是会使用执行程序服务来进行并发。它们的高级别足以隐藏管理线程的复杂性并允许线程重用。您可以将任务提交给执行程序,该执行程序将有效地充当队列,或者运行许多使用同步队列(如阻塞队列)来共享数据的任务。后者可能允许更多的灵活性,例如,对队列项进行批处理。
我还强烈推荐Guava ListenableFuture
,因为它可以解决您在使用并发时可能遇到的许多问题。
答案 2 :(得分:0)
您应该将异步管道设计为具有数据/事件依赖关系的图形。典型图由两种节点组成:
fast handler:
immediately invoked when an event happens and:
probably stores the event,
and/or calls another fast handler,
and/or submits an asynchronous task to an executor
task:
runs and issues events (that is, calls fast handlers)
所以基本上你需要开发两个独立的层:快速处理程序和任务执行程序。执行程序是通用的,可以从java.util.concurrent包中获取。快速处理程序在很大程度上取决于您的问题域,并且没有针对所有情况的通用库。例如,纯队列是一个只存储事件的快速处理程序,因此几乎没用。
如果使用I / O,则需要使用标准I / O库,以便为处理程序发出I / O事件。它可以使用线程进行同步I / O,也可以使用Selector线程或异步I / O的异步通道进行构建。
与NIO2异步通道一起使用的快速处理程序示例:
class ConnectionAcceptor implements CompletionHandler<AsynchronousSocketChannel, Void>{
AsynchronousServerSocketChannel assc;
int maxConn;// max number of simultaneous connections
int connCount=0;
/* called on creation to start listening incoming client connection requests */
void allowAccept() {
assc.accept(null, this);
}
/* called by I/O layer when a client connection requested */
public synchronized void completed(AsynchronousSocketChannel result, Void attachment) {
executor.exec(new Connection(result));
connCount++;
if (connCount<maxConn) {
allowAccept();
}
}
/* called by Connection when it is closed */
synchronized void connClosed() {
if (connCount==maxConn) {
allowAccept();
}
connCount--;
}
}
此处理程序有3个入口点并处理3种事件。类似地,可以创建用于进行读取或写入(但不是两者)的处理程序。而不是connCount,它的内部状态包含一个布尔标志,指示正在进行I / O操作,以及一个等待AsynchronousSocketChannel结束开始操作的缓冲区队列。