C#async和Java ExecutorService之间的差异
C#有一个很酷的新功能C#async和Java ExecutorService之间的差异,c#,java,future,async-await,C#,Java,Future,Async Await,C#有一个很酷的新功能 public Task<string> async f() { string r = LongCompute(); return r; } 就像 String s = f().get(); C#还有其他功能吗,或者它确实只是Java版本的一种语法糖分?(我不是C#guru,所以我可能遗漏了一些东西)。不,wait不仅仅是调用get()。还有很多 在C#中使用await表达式时,编译器会有效地创建一个continuation,这样,如果等待尚
public Task<string> async f()
{
string r = LongCompute();
return r;
}
就像
String s = f().get();
C#还有其他功能吗,或者它确实只是Java版本的一种语法糖分?(我不是C#guru,所以我可能遗漏了一些东西)。不,wait
不仅仅是调用get()
。还有很多
在C#中使用await
表达式时,编译器会有效地创建一个continuation,这样,如果等待尚未完成,则该方法可以立即返回,并仅在完成后继续处理。继续将在适当的上下文中运行-因此,如果在await
表达式之前在UI线程上,那么之后将继续在UI线程上运行,但在等待结果时不会阻塞UI线程。例如:
public async void HandleButtonClick(object sender, EventArgs e)
{
// All of this method will run in the UI thread, which it needs
// to as it touches the UI... however, it won't block when it does
// the web operation.
string url = urlTextBox.Text;
WebClient client = new WebClient();
string webText = await client.DownloadStringTaskAsync(url);
// Continuation... automatically called in the UI thread, with appropriate
// context (local variables etc) which we used earlier.
sizeTextBox.Text = string.Format("{0}: {1}", url, webText.Length);
}
归根结底,这都是语法上的糖分,但比你所展示的要复杂得多
网上已经有很多详细的信息。例如:
public async void HandleButtonClick(object sender, EventArgs e)
{
// All of this method will run in the UI thread, which it needs
// to as it touches the UI... however, it won't block when it does
// the web operation.
string url = urlTextBox.Text;
WebClient client = new WebClient();
string webText = await client.DownloadStringTaskAsync(url);
// Continuation... automatically called in the UI thread, with appropriate
// context (local variables etc) which we used earlier.
sizeTextBox.Text = string.Format("{0}: {1}", url, webText.Length);
}
- Servlet 3.0
- javafx.concurrent.Task
- 基利姆:
- Apache JavaFlow:
ExecutorService
基于线程,而C#的await
可以说是基于光纤
两者都允许多任务处理,即在并发函数(即“同时”运行的函数)之间分割计算资源。第一种多任务处理称为先发制人,而第二种多任务处理称为合作。从历史上看,先发制人的多任务处理被认为比合作式更先进、更优越。事实上,在消费者操作系统支持先发制人的多任务处理之前,计算机真的很烂。然而,先发制人的多任务处理有其缺点。它可能很难编程,而且会占用更多内存
两者之间的主要区别在于,抢占式多任务处理允许运行时(通常是操作系统本身)随时停止任何功能并启动不同的功能(并在不同的CPU上同时运行它们)。同时,协同多任务处理要求运行函数结束或自动暂停。我们大多数人都熟悉多线程形式的抢占式多任务处理,以及与之配套的谨慎编程。很少有人熟悉协作式多任务处理,现在通常称之为光纤或协同路由(在这种情况下,它是在抢占式操作系统的线程内的userland中实现的)
无论如何,关键是ExecutorService
和await
没有直接的可比性,而且await
通常并不优于真正的多线程(除了它具有良好的语法特性)。C#之所以包括wait
(并基于协作多任务),是因为平台上的主要GUI工具包不是为多线程而设计的,对它们进行重构以支持并发将需要大量的工作。协作多任务处理在UI中运行良好,因为大多数事件处理程序都很短,可以串行执行await
扩展了事件循环的概念,允许长事件处理程序暂停自己,并在渲染函数有机会运行后恢复。所有这些都发生在单个CPU核心上的单个线程中
它们的共同点在于,它们都是多任务处理的形式,而未来。get
和wait Task
都是同步的形式
正如所料,C#并非没有对线程和线程池的良好支持。同样,Java在许多库中包含fibers/co-routines/async,比如Servlet3.0和javafx.concurrent.Task
作为对Jon Skeet的回应:Continuation(如光纤的userland实现机制所称)非常重要,但线程的实现同样复杂。Jon可能被抛弃了,因为线程背后的算法在操作系统中,而不是在编译器或.NET运行时中。但是,如果你不关心哪个线程运行什么,它实际上不是等价的。第12行的延续,相当于第12行有一个线程阻塞,不是吗?唯一的好处是让所有东西都在同一个线程上运行,这通常是有用的,因为UI线程具有特权。我说的对吗?@奇兰:不太对。假设您有一个用于实现长轮询的服务器,因此可能有数十万个活动连接。在这一点上,您真的不需要每个请求的线程模型,所以您不能阻止等待“任何将触发响应的事件”。所以你需要有某种延续机制——而C#5语言的支持使得这一点非常简单;它让您编写的代码看起来和感觉上都像我们相对擅长编写的同步代码,但具有异步属性。。。抓住你了。它相当于我们最近看到的轻量级/绿色线程模型,例如golang.org,它能够标记您想要运行协同程序的真实线程。“我现在最终是对的吗?”奇兰:可能吧——但老实说,我必须了解更多关于这些的信息才能发表评论。你最好看看我所包含的链接,看看它实际上意味着什么。我在回答这个问题之前做过,但这些都解释了如何使用它,而不是为什么它们与“常规”期货不同。您已经让我参考了许多关于各种异步相关材料的文章的链接(例如,与第一个示例相比,并不真正关心wait是否使用不同的线程)。我也可以用谷歌搜索一下。如果你有什么事
public async void HandleButtonClick(object sender, EventArgs e)
{
// All of this method will run in the UI thread, which it needs
// to as it touches the UI... however, it won't block when it does
// the web operation.
string url = urlTextBox.Text;
WebClient client = new WebClient();
string webText = await client.DownloadStringTaskAsync(url);
// Continuation... automatically called in the UI thread, with appropriate
// context (local variables etc) which we used earlier.
sizeTextBox.Text = string.Format("{0}: {1}", url, webText.Length);
}