task.run多线程的坑

####问题
1.task.run默认会有线程池启用,但因为受ThreadPoolTaskScheduler的默认配置,启用多个子线程时,会1秒开启一个,如果想要减少整体运行时间并发多个线程,这其实达不到想要的效果

解决方案:

1.如果子方法有提供aync的方法,使用它

obj.getMethonAysnc();

2.指定CreateOptions为LongRunning(这样便会直接开一个新线程,而不是使用线程池)

//使用Task.Factory.StartNew比较方便的地方是方便设置TaskCreationOptions参数;
 Task.Factory.StartNew(()=> {
                Console.WriteLine("");
                Thread.Sleep(100);
            },TaskCreationOptions.LongRunning);
//new Task的使用方式,可以看到需要new一个task新类
  var task = new Task(() => { 
                Console.WriteLine("");
                Thread.Sleep(100);
            }, TaskCreationOptions.LongRunning);
 task.Start();

3.显示指定线程池的最小值和最大值

            ThreadPool.SetMinThreads(90, 100);
            ThreadPool.SetMaxThreads(90, 100);

            for (int i = 0; i < 20; i++)
            {
                // Task.Factory.StartNew();
                Task.Run(() =>
                {
                    Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.sss"));
                    Thread.Sleep(5000);
                });
            }

4.如果确实是各子线程无相关性,使用Parallel并发类

 //最简单的使用,Parallel.Invoke(...);
  public void Run1()
        {
            Thread.Sleep(2000);
            Console.WriteLine("Task 1 is cost 2 sec");
        }
        public void Run2()
        {
            Thread.Sleep(3000);
            Console.WriteLine("Task 2 is cost 3 sec");
        }

        private Stopwatch stopWatch = new Stopwatch();
        public void ParallelInvokeMethod()
        {
            stopWatch.Start();
            Parallel.Invoke(Run1, Run2);
            stopWatch.Stop();
            Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");

            stopWatch.Restart();
            Run1();
            Run2();
            stopWatch.Stop();
            Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");
        }

参考:
https://www.cnblogs.com/springsnow/p/9409205.html
https://www.cnblogs.com/walterlv/p/10236390.html
https://www.cnblogs.com/yunfeifei/p/3993401.html

了解 .NET 的默认 TaskScheduler 和线程池(ThreadPool)设置,避免让 Task.Run 的性能急剧降低

如果去掉线程池,默认会一秒生成一个新线程。
参考:https://www.cnblogs.com/soundcode/p/12160259.html
参考:https://www.cnblogs.com/atomy/p/11984179.html
重点参考:https://www.cnblogs.com/walterlv/p/10236390.html

            //ThreadPool.SetMinThreads(90, 100);
            //ThreadPool.SetMaxThreads(90, 100);
            Task.Run(() =>
            {
                while (true)
                {
                    int work = 0, com = 0;
                    ThreadPool.GetAvailableThreads(out work, out com);
                    Console.WriteLine($"{work}:{com}");
                    Thread.Sleep(100);
                }
            });


            for (int i = 0; i < 20; i++)
            {
                Task.Run(() =>
                {
                    Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.sss"));
                    Thread.Sleep(5000);
                });
            }

            Console.Read();

            return;

yapi的docker-compose内容

version: '3.1'

services:
  yapi:
    image: mrjin/yapi:latest
    #image: yapi
    # build:
      # context: .
      # dockerfile: ./yapi/Dockerfile 
    container_name: yapi
    environment:
      - VERSION=1.5.6
      - LOG_PATH=/tmp/yapi.log
      - HOME=/home
      - PORT=3000
      - ADMIN_EMAIL=admin@admin.com
      - DB_SERVER=mongo
      - DB_NAME=yapi
      - DB_PORT=27017
    restart: always
    ports:
      - 3000:3000
    volumes:
      - ./yapi.log:/home/vendors/log # log dir
    depends_on:
      - mongo
    entrypoint: "/bin/bash /wait-for-it.sh mongo:27017 -- entrypoint.sh"
    networks:
      zys_yapi:
          ipv4_address: 172.10.11.15
  mongo:
    image: mongo
    container_name: mongo
    restart: always
    ports:
      - 27017:27017
    volumes:
      - ~/data/yapi/mongodb:/data/db #db dir
    networks:
      zys_yapi:
          ipv4_address: 172.10.11.16
  mongo-express:
    image: mongo-express
    container_name: mongo-express
    restart: always
    ports:
      - 8081:8081
    networks:
      zys_yapi:
          ipv4_address: 172.10.11.17

networks:
  zys_yapi: 
    driver: bridge
    ipam:
      config:
        - subnet: 172.10.11.0/24

sqlserver分组排序

刚看到此演示sql,立马想到以前面试的时候可能遇到过,只是当时未接触过,未使用引sql解决,原来sqlserver本身就支持分组排序。
row_number() over(partition by k1 order by k2 desc)
k1表示用来分组的字段,比如学生id,k2表示排序的字段,比如学生分数