Threads(异步和多线程)
2020-12-13 14:23
标签:odi HERE chat tostring ret lse isp request requested
Task是.NET Framework3.0出现的,线程是基于线程池的,然后提供丰富的api,Thread方法很多很强大,但是太过强大,没有限制。 DoSomethingLong方法如下: Task的使用: 如果这样去调用: 如果去掉设置最大线程的代码: 运行结果如下: ThreadPool.SetMaxThreads(8, 8); 线程池是单例的,全局唯一的,设置后,同时并发的Task只有8个,而且是复用的,Task的线程是源于线程池的,全局的,请不要这样设置。 假如我想控制下Task的并发数量,改怎么做? 运行结果如下: 如果将最后一个stopwatch注释掉: 什么时候用多线程? 任务并发是时候 多线程能干嘛? 提升速度,优化用户体验。 比如,现在有一个场景,在公司开会,领导在分配任务,不能并发,因为只能有一个领导在讲话分配任务,当任务分配下去,开发们确实可以同时开始撸代码,这个是可以并发的。 现在要求,谁第一个完成,获得红包奖励(ContinueWhenAny);所有完成后,一起庆祝下(ContinueWhenAll),将其放入一个List ContinueWhenAny ContinueWhenAll 非阻塞式的回调;而且使用的线程可能是新线程,也可能是刚完成任务的线程,唯一不可能是主线程 Task.WaitAny WaitAll都是阻塞当前线程,等任务完成后执行操作,阻塞卡界面,是为了并发以及顺序控制,网站首页:A数据库 B接口 C分布式服务 D搜索引擎,适合多线程并发,都完成后才能返回给用户,需要等待WaitAll,列表页:核心数据可能来自数据库/接口服务/分布式搜索引擎/缓存,多线程并发请求,哪个先完成就用哪个结果,其他的就不管了。 假如说我想控制下Task的并发数量,该怎么做? 20个 Parallel并发执行多个Action线程,主线程会参与计算---阻塞界面。等于TaskWaitAll+主线程计算 有没有办法不阻塞? 几乎90%以上的多线程场景,以及顺序控制,以上的Task的方法就可以完成,如果你的多线程场景太复杂搞不定,那么请梳理一下你的流程,简化一下。建议最好不要线程嵌套线程,两三次勉强能懂,三层就hold不住了,更多的只能求神。 多线程异常: 线程取消: 临时变量: 为什么运行结果后,都是5呢? 临时变量问题,线程是非阻塞的,延迟启动的;线程执行的时候,i已经是5了 那么该如何解决呢? 每次都声明一个变量k去接收,k是闭包里面的变量,每次循环都有一个独立的k,5个k变量 1个i变量 这样再运行,结果就正常了。 线程安全&lock: 线程安全:如果你的代码在进程中有多个线程同时运行这一段,如果每次运行的结果都跟单线程运行时的结果一致,那么就是线程安全的 线程安全问题一般都是有全局变量/共享变量/静态变量/硬盘文件/数据库的值,只要多线程都能访问和修改 发生是因为多个线程相同操作,出现了覆盖,怎么解决? 1 Lock解决多线程冲突 Lock是语法糖,Monitor.Enter,占据一个引用,别的线程就只能等着 推荐锁是private static readonly object, A不能是Null,可以编译不能运行; B 不推荐lock(this),外面如果也要用实例,就冲突了 Threads(异步和多线程) 标签:odi HERE chat tostring ret lse isp request requested 原文地址:https://www.cnblogs.com/lonelyxmas/p/11560217.html ///
{
Task task = new Task(() => this.DoSomethingLong("btnTask_Click_1"));
task.Start();
}
{
Task task = Task.Run(() => this.DoSomethingLong("btnTask_Click_2"));
}
{
TaskFactory taskFactory = Task.Factory;
Task task = taskFactory.StartNew(() => this.DoSomethingLong("btnTask_Click_3"));
}
ThreadPool.SetMaxThreads(8, 8);
for (int i = 0; i 100; i++)
{
int k = i;
Task.Run(() =>
{
Console.WriteLine($"This is {k} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
Thread.Sleep(2000);
});
}
for (int i = 0; i 100; i++)
{
int k = i;
Task.Run(() =>
{
Console.WriteLine($"This is {k} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
Thread.Sleep(2000);
});
}
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Console.WriteLine("在Sleep之前");
Thread.Sleep(2000);//同步等待--当前线程等待2s 然后继续
Console.WriteLine("在Sleep之后");
stopwatch.Stop();
Console.WriteLine($"Sleep耗时{stopwatch.ElapsedMilliseconds}");
}
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Console.WriteLine("在Delay之前");
Task task = Task.Delay(2000)
.ContinueWith(t =>
{
stopwatch.Stop();
Console.WriteLine($"Delay耗时{stopwatch.ElapsedMilliseconds}");
Console.WriteLine($"This is ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
});//异步等待--等待2s后启动新任务
Console.WriteLine("在Delay之后");
stopwatch.Stop();
Console.WriteLine($"Delay耗时{stopwatch.ElapsedMilliseconds}");
}
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Console.WriteLine("在Sleep之前");
Thread.Sleep(2000);//同步等待--当前线程等待2s 然后继续
Console.WriteLine("在Sleep之后");
stopwatch.Stop();
Console.WriteLine($"Sleep耗时{stopwatch.ElapsedMilliseconds}");
}
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Console.WriteLine("在Delay之前");
Task task = Task.Delay(2000)
.ContinueWith(t =>
{
stopwatch.Stop();
Console.WriteLine($"Delay耗时{stopwatch.ElapsedMilliseconds}");
Console.WriteLine($"This is ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
});//异步等待--等待2s后启动新任务
Console.WriteLine("在Delay之后");
//stopwatch.Stop();
//Console.WriteLine($"Delay耗时{stopwatch.ElapsedMilliseconds}");
}
TaskFactory taskFactory = new TaskFactory();
List
TaskFactory taskFactory = new TaskFactory();
List
//阻塞当前线程,等着任意一个任务完成
Task.WaitAny(taskList.ToArray());//也可以限时等待
Console.WriteLine("准备环境开始部署");
//需要能够等待全部线程完成任务再继续 阻塞当前线程,等着全部任务完成
Task.WaitAll(taskList.ToArray());
Console.WriteLine("5个模块全部完成后,集中点评");
List
Parallel.Invoke(() => this.DoSomethingLong("btnParallel_Click_1"),
() => this.DoSomethingLong("btnParallel_Click_2"),
() => this.DoSomethingLong("btnParallel_Click_3"),
() => this.DoSomethingLong("btnParallel_Click_4"),
() => this.DoSomethingLong("btnParallel_Click_5"));
Parallel.For(0, 5, i => this.DoSomethingLong($"btnParallel_Click_{i}"));
Parallel.ForEach(new int[] { 0, 1, 2, 3, 4 }, i => this.DoSomethingLong($"btnParallel_Click_{i}"));
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 3;
Parallel.For(0, 10, options, i => this.DoSomethingLong($"btnParallel_Click_{i}"));
Task.Run(() =>
{
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 3;
Parallel.For(0, 10, options, i => this.DoSomethingLong($"btnParallel_Click_{i}"));
});
try
{
List
//多线程并发任务,某个失败后,希望通知别的线程,都停下来,how?
//Thread.Abort--终止线程;向当前线程抛一个异常然后终结任务;线程属于OS资源,可能不会立即停下来
//Task不能外部终止任务,只能自己终止自己(上帝才能打败自己)
//cts有个bool属性IsCancellationRequested 初始化是false
//调用Cancel方法后变成true(不能再变回去),可以重复cancel
try
{
CancellationTokenSource cts = new CancellationTokenSource();
List
for (int i = 0; i 5; i++)
{
Task.Run(() =>
{
Console.WriteLine($"This is btnThreadCore_Click_{i} ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
});
}
for (int i = 0; i 5; i++)
{
int k = i;
Task.Run(() =>
{
Console.WriteLine($"This is btnThreadCore_Click_{i}_{k} ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
});
}
//Test test = new Test();
//Task.Delay(1000).ContinueWith(t =>
//{
// lock (test)
// {
// Console.WriteLine("*********Start**********");
// Thread.Sleep(5000);
// Console.WriteLine("*********End**********");
// }
//});
//test.DoTest();
//C 不应该是string; string在内存分配上是重用的,会冲突
//D Lock里面的代码不要太多,这里是单线程的
Test test = new Test();
string student = "水煮鱼";
Task.Delay(1000).ContinueWith(t =>
{
lock (student)
{
Console.WriteLine("*********Start**********");
Thread.Sleep(5000);
Console.WriteLine("*********End**********");
}
});
test.DoTestString();
//2 线程安全集合
//System.Collections.Concurrent.ConcurrentQueue
上一篇:c#可选参数的一个陷阱
下一篇:复习三(JAVA基础)