问题描述
近日接受采访的时候,我得到了这个问题。
问:你写的多线程应用程序
答:是的。
问:你能解释更多的
答:我用任务
(任务并行库)开展类似部分任务,同时加载UI等待一些信息来自互联网
。这提高了我的应用程序的可用性。
问:但是,只有你已经使用太平人寿
意味着你已经写了多线程
应用程序
我:(不知道到say1什么的)
那么,什么完全是一个多线程应用程序?它是使用任务不同
?
任务的可以的用于重新present操作发生在多个线程,但他们没有的有的到。其中的可以的写在一个单独的线程永远只能执行复杂的第三方物流的应用。当你有,例如,重presents一些数据的网络请求的任务,这项任务的没有的打算创建额外的线程来实现这一目标。这样的程序是(希望)异步的,但不一定mutlithreaded
并行做多件事情在同一时间。这可能是也可能不是多个线程的结果。
让我们在这里一个类比。
下面是Bob如何做晚饭:
- 在他填补了一盆水,并煮了。
- 然后,他把在水中面食。
- 在他水渠当它做面条。
- 在他prepares成份为他的酱汁。
- 在他把所有的成分,他酱油在锅里。
- 在他自己的厨师酱。
- 在他把他的酱油在他的意大利面。
- 在他吃晚饭。
Bob已经完全煮熟同步,没有多线程,异步,并行或自己做饭吃饭的时候。
下面是简如何做晚饭:
- 在她充满了一盆水,并开始沸腾了。
- 在她prepares成份为她的酱汁。
- 她把面条在沸水中。
- 她把配料在锅里。
- 在她水渠她的意大利面。
- 她把酱油在她的意大利面。
- 在她吃她的晚餐。
简杠杆异步烹饪(没有任何多线程),以她做饭吃饭的时候实现并行。
下面是Servy如何做晚饭:
- 他告诉鲍勃烧开一壶水,放在面食准备好时,全心全意面食。
- 他告诉简,以prepare成分的调料,煮,然后在完成时为它服务过的面食。
- 在他等待Bob和Jane完成。
- 在他吃他的晚餐。
Servy杠杆多个线程(工)谁每个单独做他们的工作同步,但谁曾异步相对于彼此实现并行。
当然,这成为所有,如果我们认为更有趣的,例如,我们的炉子是否有两个燃烧器或只是一个。如果我们的炉子有两个燃烧器,然后我们两个线程,Bob和Jane,都能够做好自己的工作没有得到每个人的方式,多。他们可能会碰到的肩膀了一下,还是每一个试图抓住在同一个机柜的东西飘飞,所以他们会每放慢一个的位的,但数量不多。如果他们每个人都需要共享同一个炉头虽然那么他们就不会真正能够得到多少事都只要其他人做的工作。在这种情况下,工作不会真正得到做过任何不只是有一个人做做饭完全同步,像鲍勃做时,他对自己的速度更快。在这种情况下,我们正在做饭多线程,的但是我们煮不并行的。 不是所有的多线程工作实际上是并行工作的。这是当你在一台机器上运行多个线程使用一个CPU的会发生什么。其实你不完成工作的任何比只使用一个线程更快,因为每个线程只是轮流做工作。 (这并不意味着多线程程序都毫无意义上的一个内核的CPU,他们不是,它只是使用它们的原因不是以提高速度。)
我们甚至可以考虑这些厨师将如何使用任务并行库,看看有什么使用第三方物流的对应于每种类型的厨师做他们的工作:
所以,首先我们必须鲍勃,只是写正常的非第三方物流code,全力同步:
公共类鲍勃:ICook
{
公共IMeal·库克()
{
面食面食= PastaCookingOperations.MakePasta();
酱酱= PastaCookingOperations.MakeSauce();
返回PastaCookingOperations.Combine(面食,酱);
}
}
然后我们有简,谁启动两个不同的异步操作,那么从他们每个人的计算结果她后,等待他们两个。
公共类简:ICook
{
公共IMeal·库克()
{
任务<面食> pastaTask = PastaCookingOperations.MakePastaAsync();
任务<酱> sauceTask = PastaCookingOperations.MakeSauceAsync();
返回PastaCookingOperations.Combine(pastaTask.Result,sauceTask.Result);
}
}
由于这里提醒,简正在使用TPL,和她做了很多并行的工作,但她只使用的单个线程的做她的工作。
然后我们有Servy,谁使用 Task.Run
来创建的任务重presents做的工作在另一个线程的。他开始两个不同的工人,有他们每人两个同步做一些工作,然后等待两个工人来完成。
公共类Servy:ICook
{
公共IMeal·库克()
{
变种bobsWork = Task.Run(()=> PastaCookingOperations.MakePasta());
变种janesWork = Task.Run(()=> PastaCookingOperations.MakeSauce());
返回PastaCookingOperations.Combine(bobsWork.Result,janesWork.Result);
}
}
Recently when being interviewed, I got this question.
Q: Have you written multithreaded applications?
A: Yes
Q: Care to explain more?
A: I used Tasks
(Task Parallel library) to carry out some tasks like waiting for some info from internet while loading UI
. This improves my application usability.
Q: But, just you have used TPL
means that you have written an multithreaded
application?
Me: (Not sure what to say1)
So, whats exactly a multi-threaded application? Is it different from using Tasks
?
Tasks can be used to represent operations taking place on multiple threads, but they don't have to. One can write complex TPL applications that only ever execute in a single thread. When you have a task that, for example, represents a network request for some data, that task is not going to create additional threads to accomplish that goal. Such a program is (hopefully) asynchronous, but not necessarily mutlithreaded.
Parallelism is doing more than one thing at the same time. This may or may not be the result of multiple threads.
Let's go with an analogy here.
Here is how Bob cooks dinner:
- He fills a pot of water, and boils it.
- He then puts pasta in the water.
- He drains the pasta when its done.
- He prepares the ingredients for his sauce.
- He puts all of the ingredients for his sauce in a saucepan.
- He cooks his sauce.
- He puts his sauce on his pasta.
- He eats dinner.
Bob has cooked entirely synchronously with no multithreading, asynchrony, or parallelism when cooking his dinner.
Here is how Jane cooks dinner:
- She fills a pot of water and starts boiling it.
- She prepares the ingredients for her sauce.
- She puts the pasta in the boiling water.
- She puts the ingredients in the saucepan.
- She drains her pasta.
- She puts the sauce on her pasta.
- She eats her dinner.
Jane leveraged asynchronous cooking (without any multithreading) to achieve parallelism when cooking her dinner.
Here is how Servy cooks dinner:
- He tells Bob to boil a pot of water, put in the pasta when ready, and serve the pasta.
- He tells Jane to prepare the ingredients for the sauce, cook it, and then serve it over the pasta when done.
- He waits for Bob and Jane to finish.
- He eats his dinner.
Servy leveraged multiple threads (workers) who each individually did their work synchronously, but who worked asynchronously with respect to each other to achieve parallelism.
Of course, this becomes all the more interesting if we consider, for example, whether our stove has two burners or just one. If our stove has two burners then our two threads, Bob and Jane, are both able to do their work without getting in each others way, much. They might bump shoulders a bit, or each try to grab something from the same cabinet every now and then, so they'll each be slowed down a bit, but not much. If they each need to share a single stove burner though then they won't actually be able to get much done at all whenever the other person is doing work. In that case, the work won't actually get done any faster than just having one person doing the cooking entirely synchronously, like Bob does when he's on his own. In this case we are cooking with multiple threads, but our cooking isn't parallelized. Not all multithreaded work is actually parallel work. This is what happens when you are running multiple threads on a machine with one CPU. You don't actually get work done any faster than just using one thread, because each thread is just taking turns doing work. (That doesn't mean multithreaded programs are pointless on one cores CPUs, they're not, it's just that the reason for using them isn't to improve speed.)
We can even consider how these cooks would do their work using the Task Parallel Library, to see what uses of the TPL correspond to each of these types of cooks:
So first we have bob, just writing normal non-TPL code and doing everything synchronously:
public class Bob : ICook
{
public IMeal Cook()
{
Pasta pasta = PastaCookingOperations.MakePasta();
Sauce sauce = PastaCookingOperations.MakeSauce();
return PastaCookingOperations.Combine(pasta, sauce);
}
}
Then we have Jane, who starts two different asynchronous operations, then waits for both of them after starting each of them to compute her result.
public class Jane : ICook
{
public IMeal Cook()
{
Task<Pasta> pastaTask = PastaCookingOperations.MakePastaAsync();
Task<Sauce> sauceTask = PastaCookingOperations.MakeSauceAsync();
return PastaCookingOperations.Combine(pastaTask.Result, sauceTask.Result);
}
}
As a reminder here, Jane is using the TPL, and she's doing much of her work in parallel, but she's only using a single thread to do her work.
Then we have Servy, who uses Task.Run
to create a task that represents doing work in another thread. He starts two different workers, has them each both synchronously do some work, and then waits for both workers to finish.
public class Servy : ICook
{
public IMeal Cook()
{
var bobsWork = Task.Run(() => PastaCookingOperations.MakePasta());
var janesWork = Task.Run(() => PastaCookingOperations.MakeSauce());
return PastaCookingOperations.Combine(bobsWork.Result, janesWork.Result);
}
}
这篇关于是否使用任务(TPL)图书馆提出申请的多线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!