赞
踩
这里不会探讨它们的运行原理,考据党可以先行告退
常在.NET 开发中涉及到TASK的使用,也知道TASK是C#中对多线程编程的一种优化,
它的使用非常简单,你可以用它修饰在方法上,也可以直接传递一个Action让它直接执行
同时也可以从中获取执行的返回值,捕获异常什么的.
而之前笔者对Java的多线程的知识还停留在Thread和Runnable,
回头一想,是否Java也有类似的机制,所有看了一些文章,了解了Future的概念
发现这两个机制的风格有些相像,故记录下来
笔者之前对Java多线程的了解都停留在Thread及Runnable之上,
大多数的教程并没有涉及Callable及其配合的Future接口及其衍生的几个工具类和子接口
这里先展示一下Callable和Runnable的异同:
- Runnable r1 = new Runnable() {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- }
- };
- Callable<String> c1 = new Callable<String>() {
- @Override
- public String call() throws Exception {
- // TODO Auto-generated method stub
- return null;
- }
- };
如此就很明显了,Callable和Runnalbe的区别在于有无返回值,和是否抛出异常
众所周知,Runnable最终还是要在Thread上运行,如下
- Thread t1 = new Thread(()->{
- list.forEach(item->{System.out.println(item);});
- });
- t1.start();
但翻了翻Thread的构造函数,发现并没有可以传递Callable的重载
所以Callable应该是在Future上使用了,
现在展示一下使用Callable和Future
- public class NewTest {
-
- public static void main(String[] args) throws InterruptedException, ExecutionException {
-
- //比用Runnable只多一个返回值
- Callable<Integer> SUM_1to100 = ()->{
- int sum = 0;
- for(int i = 1;i<=100;i++)
- sum+=i;
- return sum;
- };
- //FutureTask的泛型会会约束其接受的Callable的泛型,二者必须一致
- FutureTask<Integer> task = new FutureTask<>(SUM_1to100);
- //运行线程
- task.run();
-
- System.out.println("获取了task线程任务的返回值"+task.get());
- System.out.println("线程是否结束"+task.isDone());
-
-
- }
-
- }
结果:
- 获取了task线程任务的返回值5050
- 线程是否结束true
PS:FutureTask是RunnableFuture的实现类,一般来说可以直接使用,当然也可以继承Future接口全部定制,
这是Future接口的方法
- public interface Future<V> {
- //取消线程的执行
- boolean cancel(boolean mayInterruptIfRunning);
- //是否取消
- boolean isCancelled();
- //是否完成执行
-
- boolean isDone();
- //获取返回值
-
- V get() throws InterruptedException, ExecutionException;
-
- V get(long timeout, TimeUnit unit)
- throws InterruptedException, ExecutionException, TimeoutException;
- }
RunnableFuture则继承了Future接口,和Runnable接口,这也是为什么FuctureTask可以启动线程的原因
- public interface RunnableFuture<V> extends Runnable, Future<V> {
-
- void run();
- }
- //FutureTask的部分代码
- public class FutureTask<V> implements RunnableFuture<V> {
-
- //一些状态
- private volatile int state;
- private static final int NEW = 0;
- private static final int COMPLETING = 1;
- private static final int NORMAL = 2;
- private static final int EXCEPTIONAL = 3;
- private static final int CANCELLED = 4;
- private static final int INTERRUPTING = 5;
- private static final int INTERRUPTED = 6;
-
- //用于接受传入的Callable对象
- private Callable<V> callable;
-
- private Object outcome; // non-volatile, protected by state reads/writes
-
- //它的内部有一个Thread对象,所以它的可以独立运行
- private volatile Thread runner;
-
- private volatile WaitNode waiters;
-
-
- @SuppressWarnings("unchecked")
- private V report(int s) throws ExecutionException {
- Object x = outcome;
- if (s == NORMAL)
- return (V)x;
- if (s >= CANCELLED)
- throw new CancellationException();
- throw new ExecutionException((Throwable)x);
- }
-
-
- public FutureTask(Callable<V> callable) {
- if (callable == null)
- throw new NullPointerException();
- this.callable = callable;
- this.state = NEW; // ensure visibility of callable
- }
-
-
- public FutureTask(Runnable runnable, V result) {
- this.callable = Executors.callable(runnable, result);
- this.state = NEW; // ensure visibility of callable
- }
-
-
-
-
- }
当然你也可以取消线程的执行或者捕获其中的异常.....
这些以后可以单独写一篇博客
就我现在的了解,Task有两种用法
1.先看最简单的用法:
-
- Task<int> task = new Task<int>(()=>{
- //只需要传递一个与Task泛型相同的委托即可 这就很像Callable,
- int sum = 0;
- for (int i = 1; i <= 100; i++)
- sum += i;
- return sum;
- });
-
- task.Start();
-
- Console.WriteLine("任务的结果"+task.Result+"任务是否被取消"+task.IsCanceled+"任务是否完成"+task.IsCompleted);
同样你可以通过CancellationToken来取消Task的执行,也可以捕获task的异常,获取状态....
2.配合async和await
- public static async Task<int> GetSum()
- {
-
- int result = await Sum();
- Thread.Sleep(1000);
-
- return result;
-
- }
-
- public static Task<int> Sum()
- {
- return new Task<int>(() => {
- int sum = 0;
- for (int i = 1; i <= 100; i++)
- sum += i;
- return sum;
- });
-
- }
-
- static void Main(string[] args)
- {
-
-
- var result = GetSum().Result;
-
- Console.WriteLine("result:"+result);
- }
这一块的知识比较多,如果想了解,我在此贴出一些资料
async - C# 参考 | Microsoft Docs
C# async与await的使用说明_codingriver的博客-CSDN博客_async await c#
个人认为还是C#的Task更简洁一些,毕竟TASK加委托比Future和Callable的组合更清晰一点
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。