多线程 学习笔记(一)
三个概念
进程
进程是一个程序的运行管理者,进程包括运行中的程序和程序所使用到的内存和系统资源。
线程
一个进程由很多个线程组成,不同的线程可以执行相同的函数。线程就像程序中的一个执行流(串行的)
多线程
一个程序开启多个线程(执行流)执行不同的任务。
好处:提高效率
坏处:1、线程需要占用内存,多线程越多,占用的内存就越多。 2、多线程需要协调管理,因此需要CPU时间跟踪线程。3、共享资源会 相互影响。4、太多的话导致控制复杂 而出现BUG。
Thread.CurrentThread 获取当前线程。任何一个程序在执行的过程中都会有一个主线程,程序员不另外开启新的进程进行处理时,所有处理都通过这一主线程处理。
并且当前线程是一个 Therad 类的一个静态属性,而所有的静态属性在内存中只有一份,所有线程共享一个静态属性(CurrentTherad),因此currentTherad 记录的当前CPU正在处理的进程
Start():启动线程;
Sleep(int):静态方法,暂停当前线程指定的毫秒数;
Abort():通常使用该方法来终止一个线程;
Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复;
Resume():恢复被Suspend()方法挂起的线程的执行。
Join():无参—— 阻塞处理线程去调用某个线程,直到此线程调用结束
int millisecondsTimeout(毫秒数)——唯一不同的是超过设定的毫秒数,被阻塞的进程开始运行
TimeSpan timeout——同上
代码
Thread.CurrentThread.Name = "主线程";
Thread thread1 = new Thread(new ThreadStart(StartPoint));
thread1.Name = "Thread1";
//一定要开始的线程
thread1.Start();
//阻塞主线程1秒钟后,继续执行主线程
thread1.Join(1000);
for (int i = 0; i < 10; i++)
{
Console.WriteLine("{0} is running! i={1}", Thread.CurrentThread.Name, i);
Thread.Sleep(500);
}
Console.ReadLine()
进程旅途
一、创建线程
创建线程你只要告诉线程他需要做什么就可以了,具体的是通过一个ThreadStart代理的实体,传入一个处理函数的指针就可以了,这样在启动线程时,就会去调用处理方法。
Thread thread1 = new Thread(new ThreadStart(StartPoint));
二、控制线程
thread1.IsAlive //判断一个线程是否在活跃状态
所有的线程都依附于主线程,所有的前台线程都停止,主线程才可以停止,主线程停止了,所有的后台线程都无条件停止
线程状态 (ThreadState ) 他比isAlive提供了更多的状态
Aborted:线程已停止;
AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止;
Background:线程在后台执行,与属性Thread.IsBackground有关;
Running:线程正在正常运行;
Stopped:线程已经被停止;
StopRequested:线程正在被要求停止;
Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行);
SuspendRequested:线程正在要求被挂起,但是未来得及响应;
Unstarted:未调用Thread.Start()开始线程的运行;
WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态;
进程优先级(高―〉低) 回收内存时一般从低到高进行回收
①前台进程 屏幕最前端显示的,正在于客户进行交货的
②可见进程 用户可见,但不显示在屏幕的最前端
③服务进程 service进程 如在后台进行播放音乐的工作
④后台进程
⑤空进程
由高到低分别是Highest(最高),AboveNormal(一般以上),Normal(一般),BelowNormal(一般以下),Lowest
系统默认是normal
myThread.Priority=ThreadPriority.Lowest;
通过设定线程的优先级,我们可以安排一些相对重要的线程优先执行,例如对用户的响应等等
通过上锁来避免线程冲突
Ⅰ、通过lock(this) 锁上公用对象
代码
class Program
{
static void Main(string[] args)
{
LockClass lockClass1 = new LockClass(10);
Thread t1 = new Thread(new ThreadStart(lockClass1.PrintLockIndex));
t1.Name = "第一个";
Thread t2 = new Thread(new ThreadStart(lockClass1.PrintLockIndex));
t2.Name = "第二个";
t1.Start();
t2.Start();
Console.ReadLine();
}
}
internal class LockClass
{
private int lockIndex;
public int LockIndex
{
get { return lockIndex; }
set { lockIndex = value; }
}
public LockClass(int lockIndex)
{
this.lockIndex = lockIndex;
}
public void PrintLockIndex()
{
//就是将此对象上锁,在此进程结束前部让其他进程进入
lock (this)
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(LockIndex + Thread.CurrentThread.Name);
lockIndex = lockIndex - 1;
//假如是第一个进程就让他休眠一秒,锁住后,第二个进程一直无法访问这个对象
if (Thread.CurrentThread.Name == "第一个")
{
Thread.Sleep(1000);
}
}
}
}
}
Ⅱ、锁静态变量
代码
public static int lockindex = 10;
//用来上锁的
public static object lockobject = new object();
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(PrintLockIndex));
t1.Name = "第一个线程";
Thread t2 = new Thread(new ThreadStart(PrintLockIndex));
t2.Name = "第二个线程";
t1.Start();
t2.Start();
Console.ReadLine();
}
public static void PrintLockIndex()
{
lock (lockobject)
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine(Thread.CurrentThread.Name);
}
}
}
锁定静态变量时,静态变量为int 类型是不能lock的,因为lock(引用类型变量)。因此在这个类里创建一个object类型的静态变量,这样锁定了这个类里的变量后这个类内所有的静态变量都lock了
未完待续........ 接第二部分
参考文献