C# 线程基础
1. 线程的基本概念
简单的讲进程就是程序分配在内存当中,等待处理器进行处理,请记住线程会消耗大量的操作系统资源。多个线程共享一个物理处理器将导致处理器忙于处理管理这些进程,而无法运行程序。
使用线程通常是一个操作系统的任务,试图在一个单核CPU上并行执行计算任务是没有任何意义的,可能比顺序执行花费的时间更长。
为了更好的利用现代处理器的能力,使用多线程处理程序发挥出最好的作用,这需要组织多个线程间的通讯和相互同步。
下面将学习一下 线程的生命周期,和创建线程、挂起线程、线程等待、以及终止线程。
创建一个线程操作
static void Main(string[] args)
{
//创建一个新的线程来实现输出数字
Thread t = new Thread(PrintNumber);
t.Start();
//这一行代码是在创建了一个新的线程并行执行的
PrintNumber();
Console.ReadLine();
} static void PrintNumber()
{
Console.WriteLine("Starting...");
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
}
从上面代码可以看出一个程序始终有一个主线程在执行,而Thread是创建一个新的线程执行。两者之间是同步执行的。
暂停线程
static void Main(string[] args)
{
//创建一个带暂停的进程
Thread t = new Thread(PrintNumberWithdelay);
t.Start();
//这一行就是始终执行的主线程经过(一个程序都有一个始终执行的主线程)
PrintNumber();
} static void PrintNumber()
{
Console.WriteLine("Starting...");
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
}
static void PrintNumberWithdelay()
{
Console.WriteLine("暂停...");
for (int i = 0; i < 10; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(i);
}
}
很明显,主线程已经执行完毕,而新的线程在输出暂停以后还在继续执行。每次执行都会休眠2秒钟。
线程等待
那么如何不让主线程继续往下执行,而是等待新线程执行完毕再往下执行呢。
static void Main(string[] args)
{
//创建一个带暂停的进程
Thread t = new Thread(PrintNumberWithdelay);
t.Start();
t.Join();//线程等待
Console.WriteLine("执行完毕了"); }
static void PrintNumberWithdelay()
{
Console.WriteLine("暂停...");
for (int i = 0; i < 10; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.WriteLine(i);
}
}
终止线程
static void Main(string[] args)
{
//创建一个带暂停的进程
Thread t = new Thread(PrintNumberWithdelay);
t.Start();
Thread.Sleep(TimeSpan.FromSeconds(3));
t.Abort();//终止线程
Console.WriteLine("线程终止了");
}
这段代码是给线程注入了ThreadAbortException方法,导致线程被终结,这样操作是非常危险的,因为该异常可能会导致整个应用程序都崩溃。
可以使用 ResetAbort 方法来拒绝被终止。
检测线程状态
static void Main(string[] args)
{
//创建一个带暂停的进程
Thread t = new Thread(PrintNumberWithdelay);
Thread t1 = new Thread(DoNothing);
t1.Start();
t.Start();
for (int i = 0; i < 30; i++)
{
Console.WriteLine(t.ThreadState.ToString());
}
Thread.Sleep(TimeSpan.FromSeconds(3));
t.Abort();//终止线程
Console.WriteLine("线程终止了");
Console.WriteLine(t.ThreadState.ToString());
Console.WriteLine(t1.ThreadState.ToString());
} static void PrintNumberWithdelay()
{
Console.WriteLine("开始啦...");
Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());
for (int i = 0; i < 10; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.WriteLine(i);
}
}
static void DoNothing()
{
Thread.Sleep(TimeSpan.FromSeconds(2));
}
当主程序定义了两个不同的线程,一个将会被终止,而另一个则会成功运行。线程状态位于Thread 对象的ThreadState属性中。ThreadState属性是一个C#枚举对象。
刚开始线程状态为Unstarted ,然后启动线程,并估计在一周期为30的迭代的区间中,线程状会从Running变为WitSleepJoin。
线程优先级
class ThreadSample
{
private bool _isStopped = false;
public void Stop()
{
_isStopped = true;
}
public void CountNumbers()
{
long counter = 0;
while (!_isStopped)
{
counter++;
}
Console.WriteLine("{0} 和 {1,11}" + " count={2,13}",
Thread.CurrentThread.Name,
Thread.CurrentThread.Priority,
counter.ToString("NO"));
}
} class Program
{
static void RunThreads()
{
var sample = new ThreadSample();
var threadOne = new Thread(sample.CountNumbers);
threadOne.Name = "ThreadOne";
var threadTwo = new Thread(sample.CountNumbers);
threadTwo.Name = "ThreadTwo"; threadOne.Priority = ThreadPriority.Highest;//优先级较高
threadTwo.Priority = ThreadPriority.Lowest;//优先级较低 threadOne.Start();
threadTwo.Start(); Thread.Sleep(TimeSpan.FromSeconds(2));
sample.Stop(); }
static void Main(string[] args)
{
Console.WriteLine("线程状态:{0}",Thread.CurrentThread.Priority);
Console.WriteLine("开始");
RunThreads();
Thread.Sleep(TimeSpan.FromSeconds(3));
Console.WriteLine("模拟CPU单核计算");
//让操作系统运行在第一个CPU第一个核心上
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
RunThreads();//运行时间很长
Console.WriteLine("线程终止了");
} }
此程序只用于演示,通常中无需使用这种方式。
前台线程和后台线程
class ThreadSample
{
private readonly int _iterations;
public ThreadSample(int iterations)
{
_iterations = iterations;
}
public void CountNumbers()
{
for (int i = 0; i < _iterations; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine("{0} 和 {1}",
Thread.CurrentThread.Name, i);
} }
} class Program
{
static void Main(string[] args)
{
var samppleforegroud = new ThreadSample(10);
var sampplebackgroup = new ThreadSample(20); var threadOne = new Thread(samppleforegroud.CountNumbers); threadOne.Name = "前台"; var threadTwo = new Thread(sampplebackgroup.CountNumbers); threadTwo.Name = "后台";
threadTwo.IsBackground = true; threadOne.Start();
threadTwo.Start(); } }
显示创建的是前台线程, ThreadTwo是后台线程 ,通过配置第一个线程会比第二个线程先完成,前台线程如果执行完毕,那么也会把后台线程终止掉。
向线程传递参数
class ThreadSample
{ private readonly int _iterations;
public ThreadSample(int iterations)
{
_iterations = iterations;
}
public void CountNumbers()
{
for (int i = 0; i < _iterations; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine("{0} 和 {1}",
Thread.CurrentThread.Name, i);
} }
} class Program
{
static void Count(object i)
{
CountNumbers((int)i);
} static void CountNumbers(int number)
{
Console.WriteLine(number);
} static void PrintNumber(int number)
{
Console.WriteLine(number);
} static void Main(string[] args)
{
var samppleforegroud = new ThreadSample(10); var threadOne = new Thread(samppleforegroud.CountNumbers);
threadOne.Name = "One";
threadOne.Start();
threadOne.Join();
Console.WriteLine("------------"); var threadTwo = new Thread(Count);
threadTwo.Name = "Two";
threadTwo.Start(8);
threadTwo.Join(); var threaThree = new Thread(() => CountNumbers(12));
threaThree.Name = "Three";
threaThree.Start();
threaThree.Join(); int i = 10;
var threaFour = new Thread(() => PrintNumber(i));
i = 20;
var threaFour1 = new Thread(() => PrintNumber(i));
threaFour.Start();
threaFour1.Start(); } }
使用Lock
abstract class CountBase
{
public abstract void Increment();
public abstract void Decrement(); } class Counter : CountBase
{
public int Count { get; private set; } public override void Increment()
{
Count++;
} public override void Decrement()
{
Count--;
}
} class CounterWithLock : CountBase
{
private readonly object _syncroot = new object(); public int Count { get; private set; }
public override void Increment()
{
lock (_syncroot)
{
Count++;
}
} public override void Decrement()
{
lock (_syncroot)
{
Count--;
}
}
} class Program
{
static void TestCouner(CountBase c)
{
for (int i = 0; i < 100000; i++)
{
c.Increment();
c.Decrement();
}
} static void Main(string[] args)
{
var c = new Counter(); var t1 = new Thread(() => TestCouner(c));
var t2 = new Thread(() => TestCouner(c));
var t3 = new Thread(() => TestCouner(c)); t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join(); Console.WriteLine(c.Count); var c1 = new CounterWithLock(); t1 = new Thread(() => TestCouner(c));
t2 = new Thread(() => TestCouner(c));
t3 = new Thread(() => TestCouner(c)); t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join(); Console.WriteLine(c.Count); } }
使用Monitor 锁定资源
为了避免死锁,则使用Monitor 类 来避免死锁。
Monitor.TryEnter(lock1,TimeSpan.FromSeconds(5));
C# 线程基础的更多相关文章
- Qt之线程基础
何为线程 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据计算的时候,在相同的桌面上可能有一个播放器正在播放你最喜欢的歌曲.这是一个两个进程并行工作的例 ...
- Android多线程研究(1)——线程基础及源代码剖析
从今天起我们来看一下Android中的多线程的知识,Android入门easy,可是要完毕一个完好的产品却不easy,让我们从线程開始一步步深入Android内部. 一.线程基础回想 package ...
- JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)
实现线程并发有两种方式:1)继承Thread类:2)实现Runnable接口. 线程基础 1)程序.进程.线程:并行.并发. 2)线程生命周期:创建状态(new一个线程对象).就绪状态(调用该对象的s ...
- 【windows核心编程】 第六章 线程基础
Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ① 一个是线程的内核 ...
- C#当中的多线程_线程基础
前言 最近工作不是很忙,想把买了很久了的<C#多线程编程实战>看完,所以索性把每一章的重点记录一下,方便以后回忆. 第1章 线程基础 1.创建一个线程 using System; usin ...
- Qt 线程基础(Thread Basics的翻译,线程的五种使用情况)
Qt 线程基础(QThread.QtConcurrent等) 转载自:http://blog.csdn.net/dbzhang800/article/details/6554104 昨晚看Qt的Man ...
- 线程基础(CLR via C#)
1.线程基础 1.1.线程职责 线程的职责是对CPU进行虚拟化.Windows 为每个进程豆提供了该进程专用的线程(功能相当于一个CPU).应用程序的代码进入死循环,于那个代码关联的进程会&quo ...
- Linux 系统应用编程——线程基础
传统多任务操作系统中一个可以独立调度的任务(或称之为顺序执行流)是一个进程.每个程序加载到内存后只可以唯一地对应创建一个顺序执行流,即传统意义的进程.每个进程的全部系统资源是私有的,如虚拟地址空间,文 ...
- python2 线程基础
1,感谢菜鸟教程, 线程基础:导入,创建函数,创建线和运行 import thread import time # 为线程定义一个函数 def print_time(threadName, delay ...
- 《CLR via C#》读书笔记 之 线程基础
第二十五章 线程基础 2014-06-28 25.1 Windows为什么要支持线程 25.2 线程开销 25.3 停止疯狂 25.6 CLR线程和Windows线程 25.7 使用专用线程执行异步的 ...
随机推荐
- 条件注释判断浏览器<!--[if !IE]><!--[if IE]><!--[if lt IE 6]><!--[if gte IE 6]>
<!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]--><!--[if IE]> 所有的IE可识别 <![e ...
- NoSql---MongoDB基本操作
MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语 言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引.最后由于 MongoDB 可以支 ...
- [0x00 用Python讲解数据结构与算法] 概览
自从工作后就没什么时间更新博客了,最近抽空学了点Python,觉得Python真的是很强大呀.想来在大学中没有学好数据结构和算法,自己的意志力一直不够坚定,这次想好好看一本书,认真把基本的数据结构和算 ...
- Screen Space Subsurface Scatting(Skin Rendring)
还差通透度计算,RenderMonkey截图. 参考: http://developer.download.nvidia.com/presentations/2007/gdc/Advanced_Ski ...
- C#读写Json
C#处理json文件主要有两种方式: (1)使用JavaScriptSerializer类,需要引入System.Web.Extension库,并添加下面两个引用: using System.Web; ...
- codeforces MUH and Important Things
/* 题意:给一个序列,表示每一项任务的难度,要求完成每一项任务的循序是按照难度由小到大的!输出三种符合要求的工作顺序的序列! 思路:直接看代码.... */ 1 #include<iostre ...
- 【转载】shell中 dd 命令
转载自:http://blog.chinaunix.net/uid-24958038-id-3416169.html dd if=/dev/zero of=的含义是什么? 一.dd命令的解释 dd:用 ...
- 15款提高工作效率的 Web 项目管理工具
在今天的快节奏的商业世界里,能够通过计划.组织.和管理资源池以及评估开发资源的模式来管理一个项目,是一个很艰巨的任务. 有很多现成的项目管理软件来帮助减轻项目管理的负担,并且他们几乎覆盖了所有类型的业 ...
- node log4js包
http://blog.csdn.net/heiantianshi1/article/details/43984601
- EncryptTransform
internal class EncryptTransform { //private const int c_MaxLengthOf_IV_DES = 4; //private const int ...