线程 线程池 Task
首先声明 这是读了 愉悦的绅士 文章
《Task与线程》
的一些个人总结,还是那句话,如有不对,欢迎指正
文章以代码加注释的方法展示。
//线程的创建,阻塞和同步
public static ManualResetEvent MREstop=new ManualResetEvent(false);
public static AutoResetEvent AREstop = new AutoResetEvent(false); static void Main(string[] args)
{
//使用方法注册
Thread Thread1 = new Thread(Method1);
//使用Lambda注册
Thread Thread2 = new Thread((s) =>
{
//暂停线程2,使用ManualResetEvent暂停,当使用Set方法的时候会跳过所有WaitOne();
//MREstop.WaitOne(); //暂停主线程,使用AutoResetEvent暂停,当使用Set方法的时候会跳过第一次遇到的WaitOne();
AREstop.WaitOne(); Console.WriteLine("----这是带参数方法2,参数为{0}----",s);
Console.WriteLine(DateTime.Now);
Console.WriteLine("----方法2结束----"); }); //若直接运行,会发现,Thread1和主线程的代码会交错在一起,而Thread2的代码一直在最后出现,这是因为Thread1和主线程一起运行,而Thread2延迟运行
Thread1.Start();
Thread2.Start("这是一个参数"); //取消注释,会发现Thread1和Thread2都执行完后,才会执行主线程代码
//Thread1.Join();
//Thread2.Join(); //暂停主线程,使用ManualResetEvent暂停,当使用Set方法的时候会跳过所有WaitOne();
//MREstop.WaitOne(); //暂停主线程,使用AutoResetEvent暂停,当使用Set方法的时候会跳过第一次遇到的WaitOne();
//AREstop.WaitOne(); Console.WriteLine("----这是主线程----");
Console.WriteLine(DateTime.Now);
Console.WriteLine("----主线程结束----"); } static void Method1()
{ Thread.Sleep();
Console.WriteLine("----这是不带参数方法1----");
Console.WriteLine(DateTime.Now);
Console.WriteLine("----方法1结束----"); //使用线程1开启同步,当使用Set方法的时候会跳过所有WaitOne();
//MREstop.Set(); //使用线程1开启同步,,当使用Set方法的时候会跳过第一次遇到的WaitOne(),所以主要是看Cpu先执行那个进程;
//AREstop.Set();
}
//对方法加锁
static readonly object LockObject = new object();
static int i = ;
static void Main(string[] args)
{
//实例化100条线程,执行同一个方法
for (int i = ; i < ; i++)
{
Thread Thread1 = new Thread(Method1);
Thread1.Start();
} } static void Method1()
{
//若不加锁,所有线程都可以同时访问该方法,会造成显示的结果混乱,而加了锁,就同时只能拥有一个线程访问该方法
//Monitor.Enter(LockObject); //i++非原子性操作,可能同时被多个线程执行,造成竞态,会影响运算结果,所以不能在多线程中使用。
//i++; //推荐使用线程原子性自增操作
System.Threading.Interlocked.Increment(ref i); Thread.Sleep();
Console.WriteLine("This is Thread{0} and i={1}", Thread.CurrentThread.ManagedThreadId, i);
Console.WriteLine("--------------------------------");
//加了锁必须解锁
//Monitor.Exit(LockObject); //或者使用lock(LockObject)的方法,相当于try{Monitor.Enter(LockObject);}catch{}finally{Monitor.Exit(LockObject);}的简便写法
//lock(LockObject)
//{
// System.Threading.Interlocked.Increment(ref i);
// Thread.Sleep(10);
// Console.WriteLine("This is Thread{0} and i={1}", Thread.CurrentThread.ManagedThreadId, i);
// Console.WriteLine("--------------------------------");
//} }
//线程池
public static AutoResetEvent AREstop1 = new AutoResetEvent(false);
static void Main(string[] args)
{
AutoResetEvent AREstop2 = new AutoResetEvent(false); //创建并且执行,线程池上限为CPU核心数*250,默认为后台线程
ThreadPool.QueueUserWorkItem(new WaitCallback(Method1), AREstop2); //创建并且执行
ThreadPool.QueueUserWorkItem(new WaitCallback(s =>
{
Thread.Sleep();
Console.WriteLine("----这是带参数方法2,参数为{0}----", s);
Console.WriteLine(DateTime.Now);
Console.WriteLine("----方法2结束----");
AREstop1.Set();
}), "这是一个参数"); //线程池的同步线程和线程一致,可以使用ManualResetEvent和AutoResetEvent执行。 //由于线程池没有Join方法,所以可以使用WaitAll()方法来达到所有线程执行完毕后执行主线程的效果
List<WaitHandle> handles = new List<WaitHandle>();
handles.Add(AREstop1);
// handles.Add(AREstop2);
//注意,对多个线程要使用不同的AutoResetEvent,只要数组中的AutoResetEvent接受到set指令就解锁,若全部为同一个名字
//则只要任何一个进程set之后,就会执行主线程。由于线程池默认为后台线程,一旦执行完成主线程,则其余线程自动结束
//必须数组之中的AutoResetEvent全部set后才会执行,如果该有一个没有set,都不会执行主线程。
//WaitAll最大数组上限为64
WaitHandle.WaitAll(handles.ToArray()); Console.WriteLine("----这是主线程----");
Console.WriteLine(DateTime.Now);
Console.WriteLine("----主线程结束----");
} //方法要带一个参数
static void Method1(object obj)
{
Thread.Sleep();
Console.WriteLine("----这是带参数方法1----");
Console.WriteLine(DateTime.Now);
Console.WriteLine("----方法1结束----");
AutoResetEvent AREstop2 = (AutoResetEvent)obj ;
AREstop2.Set();
}
//Task 任务 推荐使用任务来做多线程的,便于管理
public static AutoResetEvent AREstop1 = new AutoResetEvent(false);
static void Main(string[] args)
{
//Task实例化的都是后台线程,如果要更改为前台线程,需要再方法里面修改 #region Task任务 使用线程池
//{
// //实例化任务,必须手动启动,注意,方法是不能带参数的
// Task TaskFirst = new Task(Method1); // //Status可以标识当前任务的状态
// //Created:表示默认初始化任务,但是“工厂创建的”实例直接跳过。
// //WaitingToRun: 这种状态表示等待任务调度器分配线程给任务执行。
// //RanToCompletion:任务执行完毕。
// Console.WriteLine("TaskFirst的状态:{0}", TaskFirst.Status); // TaskFirst.Start(); // Console.WriteLine("TaskFirst的状态:{0}", TaskFirst.Status); // //工厂创建的直接执行
// Task TaskSecond = Task.Factory.StartNew(() =>
// { // Console.WriteLine("----这是不带参数方法2----");
// Console.WriteLine(DateTime.Now);
// Console.WriteLine("----方法2结束----");
// }); // //使用这种方法删除任务
// //CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
// //Task.Factory.StartNew(() =>
// //{ // // Console.WriteLine("----这是要删除方法4----");
// // Console.WriteLine(DateTime.Now);
// // Console.WriteLine("----要删除方法结束----");
// //}, cancelTokenSource.Token);
// //cancelTokenSource.Cancel(); // //流程控制
// {
// //没有加标识的默认使用线程池创建,若主线程结束自动结束,所以需要先堵塞主线程
// //AREstop1.WaitOne(); // //或者使用阻塞
// Task.WaitAll(TaskFirst, TaskSecond); // //也可以使用Wait()等待单个线程,你会发现下面TaskFirst的状态的状态为Running,因为主线程开始运行了,而线程TaskFirst还在运行中
// //TaskSecond.Wait(); // //Task.WaitAny 只要数组中有一个执行完毕,就继续执行主线程
// //Task.WaitAny(TaskFirst, TaskSecond); // //继续执行,在TaskFirst任务结束后继续执行,此时TaskFirst已经结束。记得加Wait(),否则主线程结束就直接结束了。
// TaskFirst.ContinueWith(NewTask =>
// {
// Console.WriteLine("----这是不带参数方法3----");
// Console.WriteLine(DateTime.Now);
// Console.WriteLine("TaskFirst的状态:{0}", TaskFirst.Status);
// Console.WriteLine("----方法3结束----");
// }).Wait(); // } // Console.WriteLine("TaskFirst的状态:{0}", TaskFirst.Status);
//}
#endregion #region Task任务 使用线程
{
////实例化任务,必须手动启动,注意,方法是不能带参数的
//Task TaskFirst = new Task(Method1, TaskCreationOptions.LongRunning);
//TaskFirst.Start();
}
#endregion #region Task任务 带参数
{
Task<int> TaskFirst = new Task<int>(((x) => { return (int)(x); }), );
TaskFirst.Start();
Console.WriteLine(" result ={0}", TaskFirst.Result); Task<string> TaskSecond = Task<string>.Factory.StartNew(new Func<object, string>(x => { return $"This is {x}"; }), );
Console.WriteLine(" result ={0}", TaskSecond.Result);
}
#endregion Console.WriteLine("----这是主线程----");
Console.WriteLine(DateTime.Now);
Console.WriteLine("----主线程结束----"); } //C# 6.0只读赋值
static object Locker { get; } = new object();
static void Method1()
{
lock (Locker)
{
Thread.CurrentThread.IsBackground = false;
Thread.Sleep();
Console.WriteLine("----这是带参数方法1----");
Console.WriteLine(DateTime.Now);
Console.WriteLine("----方法1结束----");
//AREstop1.Set();
}
}
线程 线程池 Task的更多相关文章
- 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq
常量,字段,构造方法 常量 1.什么是常量 常量是值从不变化的符号,在编译之前值就必须确定.编译后,常量值会保存到程序集元数据中.所以,常量必须是编译器识别的基元类型的常量,如:Boolean ...
- GIL 线程/进程池 同步异步
GIL 什么是GIL 全局解释器锁,本质是一把互斥锁,是加在cpython解释器上的一把锁, 同一个进程内的所有线程需要先抢到GIL锁,才能执行python代码 为什么要有GIL cpython解释器 ...
- 子进程回收资源两种方式,僵尸进程与孤儿进程,守护进程,进程间数据隔离,进程互斥锁,队列,IPC机制,线程,守护线程,线程池,回调函数add_done_callback,TCP服务端实现并发
子进程回收资源两种方式 - 1) join让主进程等待子进程结束,并回收子进程资源,主进程再结束并回收资源. - 2) 主进程 “正常结束” ,子进程与主进程一并被回收资源. from multipr ...
- C#线程 线程进阶
第四部分:高级线程 非阻塞同步 前面我们说过,即使在分配或增加字段的简单情况下,也需要同步.尽管锁定始终可以满足此需求,但是竞争性锁定意味着线程必须阻塞,从而遭受上下文切换的开销和调度的延迟,这在高度 ...
- Linux线程的实现 & LinuxThread vs. NPTL & 用户级内核级线程 & 线程与信号处理
另,线程的资源占用可见:http://www.cnblogs.com/charlesblc/p/6242111.html 进程 & 线程的很多知识可以看这里:http://www.cnblog ...
- Linux线程 之 线程 线程组 进程 轻量级进程(LWP)
Thread Local Storage,线程本地存储,大神Ulrich Drepper有篇PDF文档是讲TLS的,我曾经努力过三次尝试搞清楚TLS的原理,均没有彻底搞清楚.这一次是第三次,我沉浸gl ...
- JAVA之旅(十五)——多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止
JAVA之旅(十五)--多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止 我们接着多线程讲 一.生产者和消费者 什么是生产者和消费者?我们 ...
- python 进程和线程-线程和线程变量ThreadLocal
线程 线程是由若干个进程组成的,所以一个进程至少包含一个线程:并且线程是操作系统直接支持的执行单元.多任务可以由多进程完成,也可由一个进程的多个线程来完成 Python的线程是真正的Posix Thr ...
- 进程?线程?多线程?同步?异步?守护线程?非守护线程(用户线程)?线程的几种状态?多线程中的方法join()?
1.进程?线程?多线程? 进程就是正在运行的程序,他是线程的集合. 线程是正在独立运行的一条执行路径. 多线程是为了提高程序的执行效率.2.同步?异步? 同步: 单线程 异步: 多线程 3.守护线程? ...
随机推荐
- 2018 python面试题
在开始看面试题时,我觉得我们很有必要去了解一下市场需要什么样的python开发人员: 1.python爬虫工程师(scrapy,xpath,正则,mongdb,redis,http 协议,html) ...
- Codeforces Round #421 (Div. 2)
A: 题意:给你一本书共c页,第一天看v0页,第二天看v0+a,第二天看v0+2a以此类推,每天最多看v1页,但是后一天要重复看前一天的后l页. 代码: #include<stdio.h> ...
- 协程 及 libco 介绍
libco 是腾讯开源的一个协程库,主要应用于微信后台RPC框架,下面我们从为什么使用协程.如何实现协程.libco使用等方面了解协程和libco. why协程 为什么使用协程,我们先从server框 ...
- 如何用kaldi做孤立词识别二
基本模型没有变化,主要是调参,配置: %WER 65% 下降到了 15% 后面再继续优化... Graph compilation finish!steps/decode.sh -- ...
- Windows Server 2012 NTP时间同步
非域环境下有外网连接情况的时间同步 1. 打开组策略,Powershell键入命令:gpedit.msc 2. 在计算机策略对话框中,打开如下路径:计算机配置/管理模板/系统/Windows时间服务/ ...
- pwn入门之栈溢出练习
本文原创作者:W1ngs,本文属i春秋原创奖励计划,未经许可禁止转载!前言:最近在入门pwn的栈溢出,做了一下jarvisoj里的一些ctf pwn题,感觉质量都很不错,难度循序渐进,把自己做题的思路 ...
- ubuntu18.04LTS设置静态IP
ubuntu18.04LTS设置静态IP 因为Ubuntu18.04采用的是netplan来管理network.所以在/etc/netplan/目录下有一个以yaml结尾的文件.比如01-networ ...
- CentOS搭建FTP服务
前言: 环境:centos7.5 64 位 正文: 使用 yum 安装 vsftpd yum install vsftpd -y 安装完成后,启动 FTP 服务: service vsftpd sta ...
- Python学习笔记【第十篇】:Python面向对象进阶
保护对象的属性 如果有一个对象,当需要对其进行修改属性时,有2种方法 对象名.属性名 = 数据 ---->直接修改 对象名.方法名() ---->间接修改 为了更好的保存属性安全,即不能随 ...
- gdb remote 使用
//设置halt (gdb) set {int}0x400b0000 = 0x1(gdb) load //设置下一个pc指针的值(gdb) set {int}0x400b2000 = 0x80(gdb ...