文章目录
 前言利用委托开启线程步骤传递参数获得函数结果
     利用Thread类直接开启线程传递参数线程的优先级线程的状态注意事项
     利用线程池开启线程利用任务开启线程连续任务任务层次结构
     线程资源争夺
   
  
 
 
前言
 
我们利用线程是为了更好的利用多核pu的资源有这么几个要点, 
  在线程执行完后,我们要如何获得结果线程之间的资源争夺导致的问题线程的执行顺序,其实线程可能由于cpu资源的动态变化,运行顺序完全随机的,不可控线程开启以及消耗导致的资源浪费 每种创建线程的方式,给线程传递参数的方法,和获得结果的方法都不一样 
利用委托开启线程
 
步骤
 
将一个方法赋给委托变量变量调用BeginInvoke()方法 即可开启一个线程执行该方法 
Func<int, int,int > a = (d, b) => d+b;
            IAsyncResult ar = a.BeginInvoke(3, 4,null, null);
          
 
传递参数
 
BeginInvoke的前几个参数全部是传递参数,其次是回掉函数,最后是 自定义给回调函数传递的参数对象 属于为object类型 
获得函数结果
 
利用while 死循环判断线程执行状态,执行结束,就取得结果 
  //循环判断
            while (true)
            {
                if (ar.IsCompleted == true)
                {
                   int r = a.EndInvoke(ar);
                    Console.WriteLine("最后的结果是:"+r);
                    break;
                }
            }
 
利用指定线程的等待句柄,暂停当前线程一定时间后,如果获得指定线程的响应,就返回true,否则false 
 Func<int, int,int > a = (d, b) => d+b;
            IAsyncResult ar = a.BeginInvoke(3, 4,null, null);
            WaitHandle handle = ar.AsyncWaitHandle;
            bool res = handle.WaitOne(10); //等待10s获得,如果获得响应,返回true否则false 注意他会阻塞当前线程
            if (res==true)
            {
                int r = a.EndInvoke(ar);
                Console.WriteLine(r);
            }
 
利用回调函数(最优) 
static void Main(string[] args)
        {
            Func<int, int,int > a = (d, b) => d+b;
            a.BeginInvoke(3, 4, CallBack, a);
            Console.ReadKey();
        }
        static void CallBack(IAsyncResult ar) //系统会自动将该参数填充
        {
            Func<int, int, int> b = ar.AsyncState as Func<int, int, int>;
            int res = b.EndInvoke(ar);
            Console.WriteLine("最后得到的结果是:"+ res);
        }
 
利用Thread类直接开启线程
 
位于System.Threading下面可以直接new出来一个线程实例,将方法作为构造器参数然后 实例.Start() 才开启线程 
Thread  t = new Thread(methodName);
t.Start();
 
传递参数
 
第一种方法 
  可以在函数里面设定一个object类型的参数然后在Start方法里面传递  
void DoSm(Object str){ Console.WriteLine("输入的数据:"+str); }
Thread t  = new Thread(DoSm);
t.Start("我很好")
 
第二种方法 
  可以定义一个类,类里面包含相应字段成员,然后实例化一个对象,再将对象的方法传递给线程  
class Say
{
	private string name;
	private int age;
	
	public void Say(string name, int age)
	{
		this.name = name;
		this.age = age;
	}
	public void SayIt()
	{
		Console.WriteLine("我的名字是:"+name+"   "+"年龄为:"+age);
	}
}
Class Program
{
	static void main(string[] args)
	{
		Say say  = new Say("chaodan", 20);
		//创建线程
		Thread t = new Thread(say.SayIt);
		t.Start();
	}
}
 
或者通过Lambda表达式,其参数可以访问上下文的变量 
string name = "job";
Thread t  = new Thread(  ()=>Console.WriteLine(name)   );
t.Start()
 
线程的优先级
 
在Thead类中,可以设置Priority属性,以影响线程的基本优先级 ,Priority属性是一个ThreadPriority枚举定义的一个值。定义的级别有Highest ,AboveNormal,BelowNormal 和 Lowest 
线程的状态
 
获取线程的状态,当我们通过调用Thread对象的Start方法,可以创建线程,但是调用了Start方法之后,新线程不是马上进入Running状态,而是出于Unstarted状态,只有当操作系统的线程调度器选择了要运行的线程,这个线程的状态才会修改为Running状态。我们使用Thread.Sleep()方法可以让当前线程休眠进入WaitSleepJoin状态。使用Thread对象的Abort()方法可以停止线程。调用这个方法,会在终止要终止的线程中抛出一个ThreadAbortException类型的异常,我们可以try catch这个异常,然后在线程结束前做一些清理的工作。如果需要等待线程的结束,可以调用Thread对象的Join方法,表示把Thread加入进来,停止当前线程,并把它设置为WaitSleepJoin状态,直到加入的线程完成为止。 
注意事项
 
Thread创建的线程默认都是前台线程可以通过设置IsBackGround来设置为后台线程前台线程执行完后,会直接关闭进程,不管后台线程有没有执行完毕只要还有一个前台线程没有执行完,就不会关闭进程 
Thread  t = new Thread(methodName);
t.IsBackGround = true; //设为后台程序
t.Start();
 
利用线程池开启线程
 
位于System.Threading 下面线程池中的线程都是后台线程不能把入池的线程改为前台线程不能给入池的线程设置优先级或名称入池的线程只能用于时间比较短的任务利用线程池发起一个线程,方法必须要有一个参数这和其定义的委托类型有关系 
void ThreadMethod(object name){Console.WriteLine("我的名字:"+name);}
ThreadPool.QueueUserWorkItem(ThreadMethod);
 
利用任务开启线程
 
可以new 出来一个任务实例,将方法作为构造参数传递,然后开启任务即可通过TaskFctory.StartNew( TaskMethod ); 静态方法来开启 
//第一种方法
Task task = new Task(()=>{ Console.WriteLine("大声喊出我的名字!"); });
task.Start();
//第二种方法
TaskFactory sd = new TaskFactory();
sd.StartNew(() => Console.WriteLine(6 + 3));
 
连续任务
 
如果任务之间有依赖关系 可以使用连续任务ContinueWith的函数里面必须要有一个Task的参数 
  Task task = new Task(() => Console.WriteLine("你好"));
    task.Start();
  Task task2 = task.ContinueWith((a) => Console.WriteLine("hello"));
 
任务层次结构
 
在一个任务中启动一个新的任务,相当于新的任务是当前任务的子任务,两个任务异步执行只有子任务全部执行完了,父任务的状态才会变成RunToComPletion 
线程资源争夺
 
解决办法 使用lock关键字只有获得锁的线程才能操作该资源lock只能锁对象,引用类型死锁问题这篇博客总结的很好 
  https://www.cnblogs.com/hadoop-dev/p/6899171.html