首先声明 这是读了 愉悦的绅士 文章

菜鸟之旅——学习线程(线程和线程池)

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的更多相关文章

  1. 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq

    常量,字段,构造方法   常量 1.什么是常量 ​ 常量是值从不变化的符号,在编译之前值就必须确定.编译后,常量值会保存到程序集元数据中.所以,常量必须是编译器识别的基元类型的常量,如:Boolean ...

  2. GIL 线程/进程池 同步异步

    GIL 什么是GIL 全局解释器锁,本质是一把互斥锁,是加在cpython解释器上的一把锁, 同一个进程内的所有线程需要先抢到GIL锁,才能执行python代码 为什么要有GIL cpython解释器 ...

  3. 子进程回收资源两种方式,僵尸进程与孤儿进程,守护进程,进程间数据隔离,进程互斥锁,队列,IPC机制,线程,守护线程,线程池,回调函数add_done_callback,TCP服务端实现并发

    子进程回收资源两种方式 - 1) join让主进程等待子进程结束,并回收子进程资源,主进程再结束并回收资源. - 2) 主进程 “正常结束” ,子进程与主进程一并被回收资源. from multipr ...

  4. C#线程 线程进阶

    第四部分:高级线程 非阻塞同步 前面我们说过,即使在分配或增加字段的简单情况下,也需要同步.尽管锁定始终可以满足此需求,但是竞争性锁定意味着线程必须阻塞,从而遭受上下文切换的开销和调度的延迟,这在高度 ...

  5. Linux线程的实现 & LinuxThread vs. NPTL & 用户级内核级线程 & 线程与信号处理

    另,线程的资源占用可见:http://www.cnblogs.com/charlesblc/p/6242111.html 进程 & 线程的很多知识可以看这里:http://www.cnblog ...

  6. Linux线程 之 线程 线程组 进程 轻量级进程(LWP)

    Thread Local Storage,线程本地存储,大神Ulrich Drepper有篇PDF文档是讲TLS的,我曾经努力过三次尝试搞清楚TLS的原理,均没有彻底搞清楚.这一次是第三次,我沉浸gl ...

  7. JAVA之旅(十五)——多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止

    JAVA之旅(十五)--多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止 我们接着多线程讲 一.生产者和消费者 什么是生产者和消费者?我们 ...

  8. python 进程和线程-线程和线程变量ThreadLocal

    线程 线程是由若干个进程组成的,所以一个进程至少包含一个线程:并且线程是操作系统直接支持的执行单元.多任务可以由多进程完成,也可由一个进程的多个线程来完成 Python的线程是真正的Posix Thr ...

  9. 进程?线程?多线程?同步?异步?守护线程?非守护线程(用户线程)?线程的几种状态?多线程中的方法join()?

    1.进程?线程?多线程? 进程就是正在运行的程序,他是线程的集合. 线程是正在独立运行的一条执行路径. 多线程是为了提高程序的执行效率.2.同步?异步? 同步: 单线程 异步: 多线程 3.守护线程? ...

随机推荐

  1. web实验博客3.css-position

    css-position属性为块级元素的定位提供了可能,今天我将讲述我所了解的position属性. div.h.p元素都可以称为块级元素,display属性可以改变其框类型,其值可以对框进行设置,默 ...

  2. 如何让 Git 使用 HTTP 代理服务器

    因为我们的内部网络使用了代理,所以在 安装 OpenStack 基于 Web 的管理控制台 的时候有个小麻烦,我们的 http 代理服务器无法通过 git 协议下载 openstack-dashboa ...

  3. C#介绍RabbitMQ使用篇一HelloWorld

    RabbitMQ官网官方介绍: 译文: RabbitMQ是目前部署最广泛的开源消息代理(何为代理?可以理解为一个提供功能服务的中间件). 在全球范围内的大小企业中的生产环境中,RabbitMQ的部署两 ...

  4. navicat 几个 可用的东西

    1.常用的 表格 一启动 就进入的某某连接某某数据库某某表 2. 结构 比对(菜单栏 “工具里面”) 3.数据对比 同上 4.保持连接 5.全局查询 在工具中查找 ------在数据库或模式中查找

  5. Javascript高级编程学习笔记(59)—— 事件(3)事件对象

    事件对象 在触发DOM‘事件时,会产生一个事件对象 event 该对象包含着所有与事件有关的信息 所有浏览器都支持 event 对象但是支持的方式有所不同 DOM事件对象 兼容DOM的浏览器会将eve ...

  6. 白话TCP为什么需要进行三次握手

    阅读本文大概需要 2.3 分钟. 作者:雨林 https://www.cnblogs.com/yuilin 首先简单介绍一下TCP三次握手 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次 ...

  7. Kali学习笔记13:操作系统识别

    为什么要扫描操作系统呢? 其实和上一篇博客:<服务扫描>类似,都是为了能够发现漏洞 发现什么漏洞? 不同的操作系统.相同操作系统不同版本,都存在着一些可以利用的漏洞 而且,不同的系统会默认 ...

  8. Java异常处理 10 个最佳实践

    异常处理是Java 开发中的一个重要部分.它是关乎每个应用的一个非功能性需求,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.Java提供了几个异常处理特性,以try,catch 和 ...

  9. 【spring】从简单配置使用到深入

    一.使用前的配置 1.maven引入需要的jar包 <properties> <spring.version>4.1.6.RELEASE</spring.version& ...

  10. 基于Alpha-Beta剪枝的欢乐斗地主残局辅助

    2019年4月17日更新: 将搜索主函数优化为局部记忆化搜索,再次提高若干倍搜索速度 更新了main和player,helper无更新 #include "Player-v3.0.cpp&q ...