线程 线程池 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.守护线程? ...
随机推荐
- Reader和Writer
- all about
1.三次握手和四次挥手?2.什么是OSI七层结构?3.http vs https?4.what is Ping?基于什么协议?使用方法?5.DNS?6.cookie vs session?7.LDAP ...
- Android WebView 实现网页缩放
需要对WebView设置的内容如下: //缩放开关,设置此属性,仅支持双击缩放,不支持触摸缩放 mWebView.getSettings().setSupportZoom(true); //设置是否可 ...
- 【翻译】Neural Collaborative Filtering--神经协同过滤
[说明] 本文翻译自新加坡国立大学何向南博士 et al.发布在<World Wide Web>(2017)上的一篇论文<Neural Collaborative Filtering ...
- HTML5之日历控件
HTML5定义了几个与日期有关的新控件.支持日期控件的浏览器会提供一个方便的下拉式日历,供用户选择. 以下测试和截图都是在谷歌浏览器完成的,其他浏览器可能略有差异. 1.日期时间控件 HTML代码: ...
- 在Go语言中基础的Redis操作
在Go语言中基础的Redis操作 需要先安装redigo go get "github.com/garyburd/redigo/redis" Go语言Redis客户端的简单示例 连 ...
- python通过手机抓取微信公众号
使用 Fiddler 抓包分析公众号 打开微信随便选择一个公众号,查看公众号的所有历史文章列表 在 Fiddler 上已经能看到有请求进来了,说明公众号的文章走的都是HTTPS协议,这些请求就是微信客 ...
- 【sping揭秘】24、Spring框架对JMS的集成(无环境版,以后学MQ的时候再隆重介绍)& 任务调度和线程池
这个我也不是很了解,那么这个需要好好学习一下了 JMS有2种消息域类型 1. point to point 点对点模式 2.发布订阅模式 publish/subscribe Pub/Sub 模式 传 ...
- [译]聊聊C#中的泛型的使用(新手勿入)
写在前面 今天忙里偷闲在浏览外文的时候看到一篇讲C#中泛型的使用的文章,因此加上本人的理解以及四级没过的英语水平斗胆给大伙进行了翻译,当然在翻译的过程中发现了一些问题,因此也进行了纠正,当然,原文的地 ...
- 解决android sdk 运行出现 could not install *smartsocket* listener: cannot bind to 127.0.0.1:5037:的问题
ionic3项目,在添加android平台后,cordova run android 出现 以下问题: error: could not install *smartsocket* listener: ...