当前位置:   article > 正文

多线程对比|Java的Future使用和C#的TASK的使用_c# 有没有像java的future

c# 有没有像java的future

前言:

这里不会探讨它们的运行原理,考据党可以先行告退

常在.NET 开发中涉及到TASK的使用,也知道TASK是C#中对多线程编程的一种优化,

它的使用非常简单,你可以用它修饰在方法上,也可以直接传递一个Action让它直接执行

同时也可以从中获取执行的返回值,捕获异常什么的.

而之前笔者对Java的多线程的知识还停留在Thread和Runnable,

回头一想,是否Java也有类似的机制,所有看了一些文章,了解了Future的概念

发现这两个机制的风格有些相像,故记录下来

Java的简单多线程

笔者之前对Java多线程的了解都停留在Thread及Runnable之上,

大多数的教程并没有涉及Callable及其配合的Future接口及其衍生的几个工具类和子接口

  1. Future<V>
  2. FutureTask<V>
  3. RunnableFuture<V>
  4. SchedualFuture<V>
  5. ...

这里先展示一下Callable和Runnable的异同:

  1. Runnable r1 = new Runnable() {
  2. @Override
  3. public void run() {
  4. // TODO Auto-generated method stub
  5. }
  6. };
  7. Callable<String> c1 = new Callable<String>() {
  8. @Override
  9. public String call() throws Exception {
  10. // TODO Auto-generated method stub
  11. return null;
  12. }
  13. };

如此就很明显了,Callable和Runnalbe的区别在于有无返回值,和是否抛出异常

众所周知,Runnable最终还是要在Thread上运行,如下

  1. Thread t1 = new Thread(()->{
  2. list.forEach(item->{System.out.println(item);});
  3. });
  4. t1.start();

但翻了翻Thread的构造函数,发现并没有可以传递Callable的重载

所以Callable应该是在Future上使用了,

现在展示一下使用Callable和Future

  1. public class NewTest {
  2. public static void main(String[] args) throws InterruptedException, ExecutionException {
  3. //比用Runnable只多一个返回值
  4. Callable<Integer> SUM_1to100 = ()->{
  5. int sum = 0;
  6. for(int i = 1;i<=100;i++)
  7. sum+=i;
  8. return sum;
  9. };
  10. //FutureTask的泛型会会约束其接受的Callable的泛型,二者必须一致
  11. FutureTask<Integer> task = new FutureTask<>(SUM_1to100);
  12. //运行线程
  13. task.run();
  14. System.out.println("获取了task线程任务的返回值"+task.get());
  15. System.out.println("线程是否结束"+task.isDone());
  16. }
  17. }

结果:

  1. 获取了task线程任务的返回值5050
  2. 线程是否结束true

PS:FutureTask是RunnableFuture的实现类,一般来说可以直接使用,当然也可以继承Future接口全部定制,

这是Future接口的方法

  1. public interface Future<V> {
  2. //取消线程的执行
  3. boolean cancel(boolean mayInterruptIfRunning);
  4. //是否取消
  5. boolean isCancelled();
  6. //是否完成执行
  7. boolean isDone();
  8. //获取返回值
  9. V get() throws InterruptedException, ExecutionException;
  10. V get(long timeout, TimeUnit unit)
  11. throws InterruptedException, ExecutionException, TimeoutException;
  12. }

RunnableFuture则继承了Future接口,和Runnable接口,这也是为什么FuctureTask可以启动线程的原因

  1. public interface RunnableFuture<V> extends Runnable, Future<V> {
  2. void run();
  3. }
  1. //FutureTask的部分代码
  2. public class FutureTask<V> implements RunnableFuture<V> {
  3. //一些状态
  4. private volatile int state;
  5. private static final int NEW = 0;
  6. private static final int COMPLETING = 1;
  7. private static final int NORMAL = 2;
  8. private static final int EXCEPTIONAL = 3;
  9. private static final int CANCELLED = 4;
  10. private static final int INTERRUPTING = 5;
  11. private static final int INTERRUPTED = 6;
  12. //用于接受传入的Callable对象
  13. private Callable<V> callable;
  14. private Object outcome; // non-volatile, protected by state reads/writes
  15. //它的内部有一个Thread对象,所以它的可以独立运行
  16. private volatile Thread runner;
  17. private volatile WaitNode waiters;
  18. @SuppressWarnings("unchecked")
  19. private V report(int s) throws ExecutionException {
  20. Object x = outcome;
  21. if (s == NORMAL)
  22. return (V)x;
  23. if (s >= CANCELLED)
  24. throw new CancellationException();
  25. throw new ExecutionException((Throwable)x);
  26. }
  27. public FutureTask(Callable<V> callable) {
  28. if (callable == null)
  29. throw new NullPointerException();
  30. this.callable = callable;
  31. this.state = NEW; // ensure visibility of callable
  32. }
  33. public FutureTask(Runnable runnable, V result) {
  34. this.callable = Executors.callable(runnable, result);
  35. this.state = NEW; // ensure visibility of callable
  36. }
  37. }

当然你也可以取消线程的执行或者捕获其中的异常.....

这些以后可以单独写一篇博客

C#TASK的使用

就我现在的了解,Task有两种用法

  • 配合async和await在异步方法中使用
  • 像普通线程一样创建然后运行

1.先看最简单的用法:

  1. Task<int> task = new Task<int>(()=>{
  2. //只需要传递一个与Task泛型相同的委托即可 这就很像Callable,
  3. int sum = 0;
  4. for (int i = 1; i <= 100; i++)
  5. sum += i;
  6. return sum;
  7. });
  8. task.Start();
  9. Console.WriteLine("任务的结果"+task.Result+"任务是否被取消"+task.IsCanceled+"任务是否完成"+task.IsCompleted);

同样你可以通过CancellationToken来取消Task的执行,也可以捕获task的异常,获取状态....

2.配合async和await

  1. public static async Task<int> GetSum()
  2. {
  3. int result = await Sum();
  4. Thread.Sleep(1000);
  5. return result;
  6. }
  7. public static Task<int> Sum()
  8. {
  9. return new Task<int>(() => {
  10. int sum = 0;
  11. for (int i = 1; i <= 100; i++)
  12. sum += i;
  13. return sum;
  14. });
  15. }
  16. static void Main(string[] args)
  17. {
  18. var result = GetSum().Result;
  19. Console.WriteLine("result:"+result);
  20. }

这一块的知识比较多,如果想了解,我在此贴出一些资料

async - C# 参考 | Microsoft Docs

C# async与await的使用说明_codingriver的博客-CSDN博客_async await c#

总结一下:

个人认为还是C#的Task更简洁一些,毕竟TASK加委托比Future和Callable的组合更清晰一点

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/58566
推荐阅读
相关标签
  

闽ICP备14008679号