zoukankan      html  css  js  c++  java
  • 多线程笔记

    1)原子操作(Interlocked):所有方法都是执行一次原子读取或一次写入操作。

      2)lock()语句:避免锁定public类型,否则实例将超出代码控制的范围,定义private对象来锁定。

      3)Monitor实现线程同步

        通过Monitor.Enter() 和 Monitor.Exit()实现排它锁的获取和释放,获取之后独占资源,不允许其他线程访问。

        还有一个TryEnter方法,请求不到资源时不会阻塞等待,可以设置超时时间,获取不到直接返回false。

      4)ReaderWriterLock

        当对资源操作读多写少的时候,为了提高资源的利用率,让读操作锁为共享锁,多个线程可以并发读取资源,而写操作为独占锁,只允许一个线程操作。

      5)事件(Event)类实现同步

        事件类有两种状态,终止状态和非终止状态,终止状态时调用WaitOne可以请求成功,通过Set将时间状态设置为终止状态。

        1)AutoResetEvent(自动重置事件)

        2)ManualResetEvent(手动重置事件)

      6)信号量(Semaphore)

          信号量是由内核对象维护的int变量,为0时,线程阻塞,大于0时解除阻塞,当一个信号量上的等待线程解除阻塞后,信号量计数+1。

          线程通过WaitOne将信号量减1,通过Release将信号量加1,使用很简单。

      7)互斥体(Mutex)

          独占资源,用法与Semaphore相似。

       8)跨进程间的同步

          通过设置同步对象的名称就可以实现系统级的同步,不同应用程序通过同步对象的名称识别不同同步对象。

    ParameterizedThreadStart和ThreadStart很像,主要区别是ParameterizedThreadStart委托是带参数的方法,参数值可以是值对像,也可以是自定义对像。

    Thread.Start()启动的线程默认为前台线程。系统会待所有前台线程运行结束,应用程序域才会自动卸载。

    public class PersonInfo{
    public string name{get;set;}
    public int age{get;set;}
    public string address{get;set;}
    }
    static void ShowMessage(object obj){
        PersonInfo pinfo =obj as PersonInfo;
        Console.WriteLine("name:"+pinfo.name);
        Console.WriteLine("age:"+pinfo.age);
        Console.WriteLine("address:"+pinfo.address);
    }
    Thread thread
    =new Thread(new ParameterizedThreadStart(ShowMessage)); PersonInfo pinfo=new PersonInfo(); pinfo.name="zjh"; pinfo.age="33"; pinfo.address="zhe jiang" thread.Start(pinfo);

    线程终止:可以用Abort()方法,执行后会引发一个异常ThreadAbortException.若要想终止线程前恢复线程,可以在捕捉异常后try{}catch(ThreadAbortException ex){ thread.ResetAbort();}调用ResetAbort()方法恢复。使用thread.Join()可以保证应用程序域等待线程结束后才终止运行。

    线程池:ThradPool.GetMax(out int workThreads,out int completionPortThreads )和ThreadPool.SetMax(int workThreads,int completionPortThreads )两个方法读取和设置CLR线程池中工作者线程和I/O线程的最大线程数.获取线程池中正在工作的线程数可以使用方法ThreadPool.GetAvailableThreads(out int workThreads,out int completionPortThreads ).工程者线程有两种运行方式:1、使用ThreadPool.QueueUserWorkItem()方法,2、使用委托。

    ThreadPool有两个方法可以直接启动工作线程:ThreadPool.QueueUserWorkItem(WaitCallBack),ThreadPool.QueueUserWorkItem(WaitCallBack,object),WaitCallBack指向一个object参数的无返回值方法。

    static void AsyncCallBack(object obj){
         Thread.Sleep(1000)
           Console.WriteLine("obj:"+obj);
    }
    
    ThreadPool.QueueUserWorkItem(new WaitCallBack(AsyncCallBack));
    ThreadPool.QueueUserWorkItem(new WaitCallBack(AsyncCallBack),"test");

    委托类:CRL线程池中的线程,最灵活的最常用的方法就是使用委托的异步方法。

    delegate void mydelegate(string a);
    
    public void ShowMessage(string a){Console.WriteLine(a);}
    
    mydelegate delegate1=new mydelegate(ShowMessage);
    deletage1("test");
    
    var methods=delegate1.GetType().GetMethods();
    if(methods!=null)
    {
        foreach(MethodInfo item in methods)
      {
        Console.WriteLine("methodname:"+item.Name");
      }
    }
    public class MyDelegate:MulticastDelegate
        {
            public MyDelegate(object target, int methodPtr);
            //调用委托方法
            public virtual void Invoke();
            //异步委托
            public virtual IAsyncResult BeginInvoke(AsyncCallback callback,object state);
            public virtual void EndInvoke(IAsyncResult result);
        }
    调用Invoke()方法,对应此委托的所有方法都会执行。BeginInvoke和EndInvoke则支持委托方法的异步调用,BeginInvoke启用的线程都属性CRL线程池中的工作线程。
    IAsynceResult BeginInvoke("test",AsyncCallback callback,object state),除了最后两个参数,其它参数都是委托方法的参数,返回一个IAsyncResult接口的对像,之后调用EndInvoke(iasyncResult)方法,就可以结束异步操作,获取委托的结果。

    IAsyncResult
    public interface IAsyncResult
    {
        object AsyncState {get;}            //获取用户定义的对象,它限定或包含关于异步操作的信息。
        WailHandle AsyncWaitHandle {get;}   //获取用于等待异步操作完成的 WaitHandle。
        bool CompletedSynchronously {get;}  //获取异步操作是否同步完成的指示。
        bool IsCompleted {get;}             //获取异步操作是否已完成的指示。
    }

    判断拖托是否完成可以使用

    while(!result。IsCompleted)
    {
        //执行主线程程序。
    }
    string result=EndInvoke(result);
    
    //如果委托未执行结束,等待200毫秒
    while(!result.AsyncWaitHandle.WaitOne(200)){
         //执行主线程程序。
    }
    
    //如果有多个委托,可以使用WaitHandle,它有两个方法:WaitAny(waitHandler[],int),WainAll(waitHandler[],int);
    
    mydelegate d1=new mydelegate(ShowMessage)
    mydelegate d2
    =new mydelegate(ShowMessage)
    IAsyncResult result1
    = d1.BeginInvoke("test",null,null);
    IAsyncResult result2
    = d2.BeginInvoke("test1",null,null);
    WaitHandle[] waits
    =new WaitHandle[]{result1.AsyncWaitHandle,result2.AsyncWaitHandle} ;
    while(!WaitHandle.WaitAll(waits,200){ //执行主线程程序。 }

     使用轮询方式检测异步方法是否完成非常麻烦,而且效率不高,有见于此,可以使用异步方法的回调函数解决。

    delegate string mydelegate(string item);
    
    static void Complated(IAsyncResult result){
       string obj = result.AsyncState.ToString();//
      AsyncResult result2 = result as AsyncResult ;
      mydelegate delegate1 = result2.AsyncDelegate;
      string data=delegate1.EndInvoke(result2)
      
    }
    
    static string TestDelegate(string item){
    return DateTime.Now.Tostring("yyyy-MM-dd")+item;
    
    }
    
    mydelegate delegate1=new mydelegate(TestDelegate);
    delegate1.BeginInvoke(delegate1,Complated,"test");


     

  • 相关阅读:
    alpha冲刺1/4
    第二次作业
    第一次作业
    第一次个人作业
    第10组 Beta版本演示
    第10组 Beta冲刺(4/4)
    第10组 Beta冲刺(3/4)
    第10组 Beta冲刺(2/4)
    第10组 Beta冲刺(1/4)
    第10组 Alpha冲刺(4/4)
  • 原文地址:https://www.cnblogs.com/jyzjh/p/5962827.html
Copyright © 2011-2022 走看看