3.线程
原创
©著作权归作者所有:来自51CTO博客作者我的流浪国的原创作品,请联系作者获取转载授权,否则将追究法律责任
01.开启多线程
class Program
{
static void Main(string[] args)
{
MultiThreadDemo();
Console.ReadKey();
}
//多线程
private static void MultiThreadDemo()
{
//使用线程时首先需要创建线程,使用Thread类构造函数创建实例需要用到ThreadStart委托
//或者ParameterizedThreadStart 委托创建 Thread 类的实例
//ThreadStart 委托只能用于无返回值、无参数的方法
//ParameterizedThreadStart 委托则可以用于带参数的方法。
//线程不会直接运行,直至调用Start()方法时为止
//创建一个线程,使用Thread类创建线程时,只需提供线程入口
//(线程入口使程序知道该让这个线程干什么事)
//线程入口是通过ThreadStart代理(delegate)来提供的,
//可以把ThreadStart理解为一个函数指针,指向线程要执行的函数,
//当调用C# Thread.Start()方法后,线程就开始执行ThreadStart所代表或者说指向的函数。
ThreadStart task = () =>
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(String.Format("Thread {0} Out:{1}", Thread.CurrentThread.Name, i));
Thread.Sleep(500);
}
Console.WriteLine(String.Format("Sub Thread {0} The End", Thread.CurrentThread.Name));
};
Thread thread1=new Thread(task)
{
Name = "线程1"
};
thread1.Start();
Thread thread2 = new Thread(task)
{
Name = "线程2"
};
thread2.Start();
Thread thread3 = new Thread(task)
{
Name = "线程3"
};
thread3.Start();
Console.WriteLine("Main Thread Wait For Sub Thread");
}
02.
线程的生命周期
后台线程:在运行过程中如果宿主进程结束,线程将直接终止执行;在强制终止时,线程即终止执行不论线程代码是否执行完毕。
前台线程:在运行过程中如果宿主进程结束,线程将继续执行直至线程代码执行完毕;在强制终止时,线程即结束不论线程代码是否执行完毕。
是否为后台线程,通过线程对象的 IsBackground 属性设置
强制终止线程可通过线程对象的Abort()方法进行,同时应该在线程中进行 ThreadAbortException 异常处理,因为在强制结束未执行完成的线程时会抛出该异常。
03.join
当主线程执行到 calculate.threadAdd.Join(); 的时候,并没有继续执行,一直等到 加法线程 运算完毕之后主线程才继续运行,这不就是和MSDN中解释的一样吗?主线程现在就属于调用线程,当主线程调用了calculate.threadAdd.Join()的时候,就发生了阻塞,直到加法线程运行完毕之后,才继续运行。
现在我们在来看看Join的另外两个重载方法:Join(Int32) 和 Join(TimeSpan),这两个方法其实是一样的,输入参数说白了就是设置阻塞的等待时间,返回值是bool类型,如果线程已终止,则为 true,否则返回 false
class Program
{
static void Main(string[] args)
{
Calculate calculate=new Calculate();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("主线程输出:准备进行加法运算:");
calculate.threadAdd.Start();
//主线程现在就属于调用线程,当主线程调用了calculate.threadAdd.Join()的时候,就发生了阻塞,直到加法线程运行完毕之后,才继续运行。
calculate.threadAdd.Join();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("主线程输出:运算完毕");
Console.ReadKey();
}
}
class Calculate
{
public Thread threadAdd;
public Calculate()
{
threadAdd =new Thread(Add);
}
private void Add()
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("进入加法计算");
Thread.Sleep(2000);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("加法运算结果: x={0} y={1} x+y={2}", 1, 2, 1 + 2);
}
}
04.
主线程遇到 calculate.threadAdd.Join(); 和 calculate.threadSub.Join(); 肯定会发生阻塞,等待这两个线程完成后,才会继续执行,这个不容质疑。然后我们看加法线程和减法线程,这两个线程几乎同时执行,谁先执行,我们是不可预期的。比如先执行加法线程,当执行到Thread.Sleep(5000),的时候,加法线程休眠5s,减法线程由于调用了 threadAdd.Join(1000); 所以减法线程会阻塞1s ,1s 之后由于加法线程还没有执行完成,所以 返回值为 false,减法线程继续执行,减法线程执行完毕后,又过了一会,加法线程才继续执行。这样就会得出我们上面的运行结果。
using System;
using System.Threading;
namespace ThreadFive
{
class Program
{
static void Main(string[] args)
{
Calculate calculate=new Calculate();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("主线程输出:准备进行加法运算:");
calculate.threadAdd.Start();
calculate.threadSub.Start();
calculate.threadAdd.Join();
calculate.threadSub.Join();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("主线程输出:运算完毕");
Console.ReadKey();
}
}
class Calculate
{
public Thread threadAdd;
public Thread threadSub;
public Calculate()
{
threadAdd =new Thread(Add);
threadSub=new Thread(Sub);
}
private void Add()
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("进入加法计算");
Thread.Sleep(4000);
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("加法运算结果: x={0} y={1} x+y={2}", 1, 2, 1 + 2);
}
private void Sub()
{
bool b = threadAdd.Join(1000); //1S之后加法线程没有执行完成返回 fslse
if (b)
{
Console.WriteLine("加法运算已经完成,进入减法法计算");
}
else
{
Console.WriteLine("加法运算超时,先进入减法法计算");
}
Thread.Sleep(2000);
Console.WriteLine("进入减法运算");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("减法运算结果: x={0} y={1} x-y={2}", 10, 2, 10 - 2);
}
}
}