zoukankan      html  css  js  c++  java
  • ContinueWhenAll 实现线程的多重依赖

    在进行多线的开发中,经常会遇到类似这样的问题

    线程T4依赖T1,T2,T3的结果,T6又依赖T5和T4的结果。在有限可控的范围内,我们可以通过信号量来同步期间的关系,但是如果是在服务器或者线程数很庞大的情况下,就要三思了。

    因为使用信号量意味着1,创建所有的线程并启动。2,很多线程会因为没有执行到它而阻塞。

    我们知道在windows下,一个线程会耗费很多资源,其他的不说,光是内存就硬占1M。同时启很多个线程,并且其中大部分都在阻塞中,那么就意味着资源的大量浪费。

    在.net 4.0中,新加入了Task类型,将任务和线程分离开了,CLR会根据算法自动生成线程,分配给task去执行。这样就很适合我们要求的这种场景。

    使用ContinueWhenAll来处理这种纠结的线程间依赖关系,是再好不过的了

        internal class Program
        {
            private static void Main(string[] args)
            {
    
                var cts = new CancellationTokenSource();
    
                var tf = new TaskFactory<Int32>(cts.Token, TaskCreationOptions.AttachedToParent,
                                                TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
    
                Task<Int32> t1 = new Task<int>(() =>
                                                   {
    
    
    
                                                       int sum = 0;
    
                                                       Console.WriteLine("task1 Start\n");
    
                                                       sum = Sum(cts.Token, 1, 2);
    
                                                       Console.WriteLine("task1 Done\n");
    
                                                       return sum;
    
                                                   });
    
                Task<Int32> t2 = new Task<int>(() =>
                                                   {
    
                                                       int sum = 0;
    
                                                       Console.WriteLine("task2 Start\n");
    
                                                       sum = Decline(cts.Token, 1, 2);
    
                                                       Console.WriteLine("task2 Done\n");
    
                                                       return sum;
    
                                                   });
    
                Task<Int32> t3 = new Task<int>(() =>
                                                   {
    
                                                       int sum = 0;
    
                                                       Console.WriteLine("task3 Start\n");
    
                                                       sum = Mulex(cts.Token, 1, 2);
    
                                                       Console.WriteLine("task3 Done\n");
    
                                                       return sum;
    
                                                   });
    
    
    
                Task<Int32> t4 = tf.ContinueWhenAll(new[] {t1, t2, t3}, (compelers =>
                                                                             {
    
                                                                                 int sum = compelers[0].Result;
    
                                                                                 int declines = compelers[1].Result;
    
                                                                                 int mulex = compelers[2].Result;
    
                                                                                 Console.WriteLine("Task4 done\n");
    
                                                                                 return sum + declines + mulex;
    
                                                                             }), CancellationToken.None);
    
                Task<Int32> t5 = new Task<int>(() =>
                                                   {
    
                                                       int sum = 0;
    
                                                       Console.WriteLine("task5 Start\n");
    
                                                       for (int i = 0; i < 100; i++)
                                                       {
    
                                                           Thread.Sleep(500);
    
                                                           sum = 10/2;
    
                                                       }
    
                                                       Console.WriteLine("task5 Done\n");
                                                       return sum;
    
                                                   });
    
                Task<Int32> t6 = tf.ContinueWhenAll(new[] {t4, t5}, compelets =>
                                                                        {
    
                                                                            int s1 = compelets[0].Result;
    
                                                                            int s2 = compelets[1].Result;
    
                                                                            Console.WriteLine("Task6 Done\n");
    
                                                                            return s1 + s2;
    
                                                                        }, CancellationToken.None);
    
                t6.ContinueWith(task =>
                                    {
    
                                        int result = task.Result;
    
                                        Console.WriteLine("All Done\n Result is {0}", result);
    
                                    });
    
                Thread.Sleep(200);
    
                t1.Start();
    
                t2.Start();
    
                t3.Start();
    
                t5.Start();
    
                Console.ReadLine();
    
            }
    
            private static int Mulex(CancellationToken token, int a1, int a2)
            {
    
                int result = 0;
    
                for (int i = 0; i < 100; i++)
                {
    
                    result = a1*a2;
    
                    Thread.Sleep(50);
    
                    token.ThrowIfCancellationRequested();
    
                }
    
                return result;
    
            }
    
            private static int Decline(CancellationToken token, int a1, int a2)
            {
    
                int decline = 0;
    
                for (int i = 0; i < 100; i++)
                {
    
                    decline = a1 - a2;
    
                    Thread.Sleep(50);
    
                    token.ThrowIfCancellationRequested();
    
                }
    
                return decline;
    
            }
    
            private static int Sum(CancellationToken token, int a1, int a2)
            {
    
                int sum = 0;
    
                for (int i = 0; i < 100; i++)
                {
    
                    sum = a1 + a2;
    
                    Thread.Sleep(50);
    
                    token.ThrowIfCancellationRequested();
    
                }
    
                return sum;
    
            }
        }
    

      

    运行结果,会先执行t1,t2,t3,t5.等t1,t2,t3执行完毕,会开始执行t4.

    t4,t5运行完后会启动运行t6.

  • 相关阅读:
    利用兼容DC和兼容位图实现图形重绘
    MFC实现文件打开和保存功能实现
    CFile文件操作示例
    利用互斥对象实现线程同步的实例说明
    bootstrap3 input 验证样式【转】
    js event 冒泡和捕获事件详细介绍【转】
    Html+Ajax+Springmvc+Mybatis,不用JSP【转】
    hp电脑重装win7 64位 后 所有软件都装不上问题【转】
    bootstrap 模态 modal 小例子【转】
    servlet 获取 post body 体用流读取为空的问题【转】
  • 原文地址:https://www.cnblogs.com/suriyel/p/2728748.html
Copyright © 2011-2022 走看看