线程 线程池 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.守护线程? ...
随机推荐
- dialog记录
.gyzq{ &.dialog{ background: rgba(83,83,83,0.50); width: 100%; height: 100%; position: fixed; ov ...
- 判断是否为AVL树
时间复杂度:O(n) // 判断是否为AVL树 public int isAVL(TreeNode node) { if (node == null) { return 0; } int left = ...
- C++ 使用Lambda
基础使用: C++中的Lambda表达式详解 c++11的闭包(lambda.function.bind) C++ lambda作为函数参数,实现通用的查找接口 C++11系列-lambda函数 进阶 ...
- 与其他相似软件对比,win10中个人助理conrtana具备哪些独特的功能
目前,Cortana 可以回答各种口头问题,直接设置提醒,或者提供位置导航,并支持语音命令处理各项事务,而且随时间的推移学习更多内容,从而变得更加个性化和实用.简单而言,集成在 Edge 浏览器中的 ...
- 使用sklearn估计器构建K-Means聚类模型
实例要求:以sklearn库自带的iris数据集为例,使用sklearn估计器构建K-Means聚类模型,并且完成预测类别功能以及聚类结果可视化. 实例代码: import pandas as pd ...
- 腾讯开源 MMKV — 基于mmap的高性能通用key-value组件
一.介绍 MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强.从 2015 年中至今,在 iOS 微信上使用已有近 3 ...
- Ubuntu16.04.1 安装Nginx
Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 Igor Sysoev ...
- HttpServlet的转发和重定向
HttpServletResponse重定向 1.HTTP协议规定了一种重定向的机制,重定向的运作流程如下 用户在浏览器输入特定的URL,请求访问服务端的某个组件. 服务端的组件返回一个状态码为302 ...
- js-完整轮播图
js-完整轮播图 今天写一个完整的轮播图,首先它需要实现三个功能:1.鼠标放在小圆点上实现轮播.2.点击焦点按钮实现轮播.3.无缝自动轮播. 轮播图的原理: 一系列的大小相等的图片平铺,利用CSS布 ...
- DCT(离散余弦变换)算法原理和源码(python)
原理: 离散余弦变换(DCT for Discrete Cosine Transform)是与傅里叶变换相关的一种变换,它类似于离散傅里叶变换(DFT for Discrete Fourier Tra ...