简体   繁体   English

C#async和Java ExecutorService之间的差异

[英]Differences between C# async and Java ExecutorService

C# has a cool new feature C#有一个很酷的新功能

public Task<string> async f()
{
    string r = LongCompute();
    return r;
}

but isn't that equivalent to 但并不等同于

public Future<String> f() {
    return Globals.executorService.submit(new Callable<String>() {
        public String call() throws Exception {
            String r = longCompute();
            return r;
        }
    });
}

where in Java you have more flexibility to choose the threadpool in which the task would run. 在Java中,您可以更灵活地选择运行任务的线程池。

What about await? 怎么样等待? It's equivalent to just calling get 这相当于只调用get

string s = await f();

is just like 就像

String s = f().get();

Is there anything more to C#, or is it indeed just a syntactic sugar to the Java version? C#还有什么,或者它确实只是Java版本的语法糖? (I'm not a C# guru, so I might be missing something). (我不是C#guru,所以我可能会遗漏一些东西)。

No, await is not like just calling get() . 不, await不是像刚才调用get() There's considerably more to it. 相当多的吧。

When you use an await expression in C#, the compiler effectively creates a continuation, so that if the awaitable hasn't completed yet, the method can immediately return, and continue processing only when it's completed. 在C#中使用await表达式时,编译器会有效地创建一个continuation,因此如果awaitable尚未完成,则该方法可以立即返回,并且只有在完成时才继续处理。 The continuation will run in an appropriate context - so if you're on a UI thread before the await expression, you'll continue on the UI thread afterwards, but without blocking the UI thread while you're waiting for the result. 延续将在适当的上下文中运行 - 因此,如果您在await表达式之前处于UI线程上,则之后将继续在UI线程上,但在等待结果时不会阻止UI线程。 For example: 例如:

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); 
}

Ultimately it's all syntactic sugar, but much more complicated sugar than what you've shown. 最终,它的所有语法糖,但比你出什么样的糖复杂。

There's a lot of detailed information available on the web already. 网上已有很多详细信息。 For example: 例如:

Jon didn't explain the real point . 乔恩没有解释真正的观点

Java's ExecutorService is based on threads , while C#'s await can be said to be based on fibers . Java的ExecutorService基于线程 ,而C#的await可以说是基于光纤

Both allow multitasking, which splits computing resources between concurrent functions (ie, functions that run "simultaneously"). 两者都允许多任务处理,其在并发功能(即,“同时”运行的功能)之间分割计算资源。 The first kind of multitasking is called pre-emptive , while the second co-operative . 第一种多任务被称为先发制人 ,而第二个合作社 Historically, preemptive multitasking was considered more advanced and superior to cooperative. 从历史上看,先发制人的多任务处理被认为更先进,更优于合作。 Indeed, before preemptive multitasking became supported by consumer operating systems, computers really sucked. 实际上,在先发制人的多任务处理被消费者操作系统支持之前,计算机确实很糟糕。 However, preemptive multitasking has its shortcomings. 但是,抢先式多任务处理有其缺点。 It can be hard to program for, and it uses more memory. 它可能很难编程,并且它使用更多的内存。

The main difference between the two is that preemptive multitasking allows the runtime (usually, the operating system itself) to stop any function at any time and start a different function (and to run them simultaneously on different CPUs). 两者之间的主要区别在于抢占式多任务处理允许运行时(通常是操作系统本身)随时停止任何功能并启动不同的功能(并在不同的CPU上同时运行它们)。 Meanwhile, cooperative multitasking requires the running function to end or to voluntarily pause. 同时,协作式多任务处理需要运行功能结束或自动暂停。 Most of us are familiar with preemptive multitasking in the form of multithreading, as well as the kind of careful programming that goes with it. 我们大多数人都熟悉多线程形式的抢占式多任务处理,以及随之而来的精心编程。 Fewer are familiar with cooperative multitasking, which nowdays is often called fibers or coroutines (in which case it's implemented in userland inside the threads of a preemptive OS). 很少有人熟悉协作式多任务处理,现在通常称为光纤或协同程序(在这种情况下,它是在抢先操作系统的线程内的用户空间中实现的)。

Anyway, the point is that ExecutorService and await are not directly comparable, and await isn't, in general, superior to real multithreading (except that it features nice syntactic sugar). 无论如何,重点是ExecutorServiceawait不能直接比较,并且await通常不优于真正的多线程(除了它具有很好的语法糖)。 C#'s reason for including await (and basing it on cooperative multitasking) is that the major GUI toolkits on the platform are not designed for multithreading and refactoring them to support concurrency would take a boatload of work. C#包含await (并以协同多任务为基础)的原因是平台上的主要GUI工具包不是为多线程而设计的,重构它们以支持并发性需要大量的工作。 Cooperative multitasking works well for the UI because most of the event handlers are short and can be executed serially. 协作式多任务处理适用于UI,因为大多数事件处理程序都很短并且可以串行执行。 await extends the concept of the event loop by letting long event handlers pause themselves and resume after the rendering function gets a chance to run. await通过让长事件处理程序暂停自身并在渲染函数有机会运行后恢复来扩展事件循环的概念。 All of this happens in a single thread on a single CPU core. 所有这些都发生在单个CPU核心上的单个线程中。

Where they both find common ground is that they're both forms of multitasking, and Future.get and await Task are both forms of synchronization. 它们都找到共同点的地方在于它们都是多任务处理的形式,而Future.getawait Task都是同步的形式。

As can be expected, C# is not without good support for threads and thread pools. 可以预料,C#并不是没有对线程和线程池的良好支持。 Likewise, Java contains fibers/co-routines/async in many libraries, such as Servlet 3.0 and javafx.concurrent.Task . 同样,Java在许多库中包含光纤/协同例程/异步,例如Servlet 3.0和javafx.concurrent.Task

In response to Jon Skeet: Continuation (as the userland implementation mechanism of fibers is called) is non-trivial, but threads are no less sophisticated in their implementation. 回应Jon Skeet: Continuation (因为调用光纤的用户区实现机制)是非平凡的,但线程的实现并不复杂。 Jon may have been thrown off because the algorithms behind threads are in the OS rather than in the compiler or .NET runtime. Jon可能已被抛弃,因为线程背后的算法是在OS中而不是在编译器或.NET运行时中。

Just to extend correct Jon Skeet's answer. 只是为了扩展正确的Jon Skeet的答案。

The is no Java analog of C# await expressions. 它不是C#等待表达式的Java模拟。 Hoverer, some Java frameworks have same functionality: Hoverer,一些Java框架具有相同的功能:

In fact, they generate routines or state-machine code on-fly. 实际上,它们会在运行时生成例程或状态机代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM