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.

  • 相关阅读:
    CF1386C Joker
    P7486 「StOI2031」彩虹
    CF1516E Baby Ehab Plays with Permutations
    重拾莫比乌斯反演
    联合省选 2020 补题记录
    拉格朗日插值如何插出系数
    NOI Online 2021 补题
    Re:从0开始的多项式生活
    LOJ #6485. LJJ 学二项式定理
    P5591 小猪佩奇学数学
  • 原文地址:https://www.cnblogs.com/suriyel/p/2728748.html
Copyright © 2011-2022 走看看