线程 线程池 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.守护线程? ...
随机推荐
- [转]CSS clear both清除浮动
DIV+CSS clear both清除产生浮动 我们知道有时使用了css float浮动会产生css浮动,这个时候就需要清理清除浮动,我们就用clear样式属性即可实现. 接下来我们来认识与学习cs ...
- html5 css选择器。 井号,句号的区别
.理解CSS的样式组成CSS里的样式表是有规则组成的,每条规则有三个部分组成:1.选择器(如下面例子中的:“body”),告诉浏览器文档的哪个部分受规则影响:2.属性(如实例中的font-family ...
- 省钱版----查找 IoT 设备TTL线序__未完待续
作者:仙果 原文来自:省钱版—-查找 IoT 设备TTL线序 省钱版----查找 IoT 设备TTL线序__未完待续 缘由 在IoT固件调试分析的过程中,建议首先在IoT设备的板子上焊接调试线,这是能 ...
- 【云盘资料】Sql注入从菜鸟到高手系列教程
[云盘资料]Sql注入从菜鸟到高手系列教程 ps:Sql注入从菜鸟到高手系列教程 链接:阅读原文获取资料:http://bbs.ichunqiu.com/thread-6851-1-1.html 反馈 ...
- JavaScript之DOM对象获取(1)
我们在操作html中的节点的时候,第一步就需要获取到对应节点(元素),才能有后续的操作.获取节点的方式有很多 1.document.getElementById(‘id值’) 通过id精确的选中某一个 ...
- JSTL标签库的基本教程之核心标签库(二)
JSTL标签库的基本教程之核心标签库(二) 核心标签库 标签 描述 <c:out> 用于在JSP中显示数据,就像<%= ... > <c:set> 用于保存数据 & ...
- node.js使用免费的阿里云ip查询获取ip所在地
在项目过程中,我们常常需要获取IP的所在地.而这一功能一般都是通过一些数据网站的对外接口来实现,这些接口一般情况下都是付费使用的.在这篇文章中我将记录,基于node.js的阿里云免费IP地址查询接口的 ...
- 第34节:Java当中的异常
Java当中的异常 了解Java当中的异常,那么什么是异常呢?异常又有什么分类呢?异常中的特殊结构:try...catch...finally 结构的使用方法. 异常是一种对象,是靠虚拟机产生的,异常 ...
- Spark基础-scala学习(五、集合)
集合 scala的集合体系结构 List LinkedList Set 集合的函数式编程 函数式编程综合案例:统计多个文本内的单词总数 scala的集合体系结构 scala中的集合体系主要包括:Ite ...
- 9102年了,汇总下HttpClient问题,封印一个
如果找的是core的HttpClientFactory 出门右转. 官方写法,高并发下,TCP连接不能快速释放,导致端口占完,无法连接 Dispose 不是马上关闭tcp连接 主动关闭的一方为什么不能 ...