一、概念
什么是线程?线程是程序执行最基本单元,它是一种数据结构。
百度百科是这样描述的:
线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
维基百科是这样定义的:
In computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system.[1] The implementation of threads and processes differs between operating systems, but in most cases a thread is a component of a process. Multiple threads can exist within one process, executing concurrently and sharing resources such as memory, while different processes do not share these resources. In particular, the threads of a process share its executable code and the values of its variables at any given time.
在计算机科学当中,线程是操作系统能够进行调度的最小单位。每个操作系统的线程和进程的实现有所不同,但是大多情况下,线程是进程的一个组件。一个进程中可以有许多线程共存,可并发执行以及共享资源(如内存),而不同进程间不会共享资源,尤其多线程在任何时候可以共享可执行代码,变量值。
什么是进程?进程是运行中的程序,拥有系统分配的资源。
百度百科的定义:
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
维基百科的定义:
In computing, a process is an instance of a computer program that is being executed. It contains the program code and its current activity. Depending on the operating system (OS), a process may be made up of multiple threads of execution that execute instructions concurrently.[1][2]
在计算机中,进程是计算机程序执行的实例。它包含程序代码以及当前的活动。依赖于操作系统,一个进程是由多个并行,可执行线程组成的。
二、线程的分类
三、线程的状态
四、.net中如何开启一个线程
1、直接new一个Thread,默认是前台线程。由于线程代表了某一类方法的运行,所以得用到委托。我们先看看Thread的构造函数:
public Thread(ParameterizedThreadStart start) { if (start == null) { throw new ArgumentNullException("start"); } this.SetStartHelper(start, 0); } public Thread(ThreadStart start) { if (start == null) { throw new ArgumentNullException("start"); } this.SetStartHelper(start, 0); }
我们看到Thread构造函数接收 ThreadStart和ParameterizedThreadStart类型的start。那么分别看它们是什么类型:
public delegate void ParameterizedThreadStart(object obj);
public delegate void ThreadStart();
原来一个是带参数的委托,另一个是不带参数的委托。
2、定义一个Timer。
public Timer(TimerCallback callback) { int num = -1; int num2 = -1; StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; this.TimerSetup(callback, this, (uint) num, (uint) num2, ref lookForMyCaller); } public Timer(TimerCallback callback, object state, int dueTime, int period) { if (dueTime < -1) { throw new ArgumentOutOfRangeException("dueTime", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } if (period < -1) { throw new ArgumentOutOfRangeException("period", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1")); } StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; this.TimerSetup(callback, state, (uint) dueTime, (uint) period, ref lookForMyCaller); }
System.Threading.Timer,构造函数接收 TimerCallback 类型,我们看下此类型的定义:
public delegate void TimerCallback(object state);
原来是可以传参的委托。
3、从线程池中取出的线程
ThreadPool.QueueUserWorkItem
New Task
public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable
从Task类的定义看,它实现了线程池工作者接口,实现了异步。
public Task(Action action, System.Threading.CancellationToken cancellationToken) : this(action, null, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; this.PossiblyCaptureContext(ref lookForMyCaller); }
这是它众多构造函数中一个,接收Action类型的委托,cancellationToken为协作式取消线程执行的一个对象。
Task.Factory.StartNew
Task.Run
Task功能非常强大,可参考其它文章理解。
五、多线程的异步
异步处理的三个步骤:
1、启动处理 2、实际处理(比较耗时) 3、任务完成后的处理
第一步由主线程完成,第二步由子线程完成,第三步如果由主线程完成,那么就牵扯到主线程和子线程之间的同步问题,因为主线程要获取子线程执行的结果,以便完成第三步。如果第三步由子线程完成,那么就可避免这个问题,因为第二步和第三步都由子线程完成,它们是由同一个线程来处理的。
异步处理需要IAsyncResult,无论是事件,还是委托的Begin、End方法,都是基于IAsyncResult实现的。
六、多线程的同步
同步牵扯到对系统资源的竞争或者线程间需要协作完成某些任务。可参考我的其它文章。