zoukankan      html  css  js  c++  java
  • attributes && reflections &&Thread&&Synchronization

    1.属性和反射

    属性是对目标元素的相关数据的代表。

    同时C# 还具有一个反射系统,可用来检索用自定义属性定义的信息。(否则自定义属性没什么意义,不过老师说可以用一些软件来查看,比如书上说的:ILDasm)

    老师讲的比较快,听得不是很清楚,后来翻了翻书,看到“自定义属性”的内容,进行了尝试。

    这个例子是把程序的错误信息绑定到代码的特定修正中(特定修正?),然后利用反射将元数据输出到console流里。

     1 namespace CustomAttributes
     2 {
     3     //create attributes
     4     [AttributeUsage(AttributeTargets.Class|AttributeTargets.Constructor|AttributeTargets.Field
     5                     |AttributeTargets.Method|AttributeTargets.Property,AllowMultiple = true)]
     6     public class BugFixAttribute : System.Attribute
     7     {
     8         //private class member
     9         private int bugID;
    10         private string comment;
    11         private string date;
    12         private string programmer;
    13         //按声明顺序导入参数  构造函数
    14         public BugFixAttribute(int bugID, string programmer, string date)
    15         {
    16             this.bugID = bugID;
    17             this.programmer = programmer;
    18             this.date = date;
    19         }
    20         //只读参数访问器
    21         public int BugID
    22         {
    23             get { return bugID; }
    24         }
    25         //带名参数的特征
    26         public string Comment
    27         {
    28             get { return comment; }
    29             set { comment = value; }
    30         }
    31         public string Date
    32         {
    33             get { return date; }
    34         }
    35         public string Programmer
    36         {
    37             get { return programmer; }
    38         }
    39          
    40     }
    41     [BugFixAttribute(121,"mark","15/04/30")]
    42     [BugFixAttribute(107,"mark","15/05/02",Comment= "fixed off by one error")]
    43 
    44     public class MyMath
    45     {
    46         public double f1(double p1)
    47         {
    48             return p1 + f2(p1);
    49         }
    50         public double f2(double p1)
    51         {
    52             return p1 / 3;
    53         }
    54     }
    55     public class Tester
    56     {
    57         public static void Main ()
    58         {
    59             MyMath mm = new MyMath();
    60             Console.WriteLine("call f(7).result:{0}", mm.f1(7));
    61             
    62             //获得成员信息并检索自定义属性
    63             System.Reflection.MemberInfo inf = typeof(MyMath);
    64             object[] attributes;
    65             attributes = inf.GetCustomAttributes(typeof(BugFixAttribute), false);
    66 
    67             //遍历属性并检索
    68             foreach( Object attribute in attributes)
    69             {
    70                 BugFixAttribute bfa = (BugFixAttribute)attribute;
    71                 Console.WriteLine("
    BugID:{0},bfa {0}", bfa.BugID);
    72                 Console.WriteLine("Programmer: {0}", bfa.Programmer);
    73                 Console.WriteLine("Date: {0}", bfa.Date);
    74                 Console.WriteLine("Comment: {0}", bfa.Comment);
    75             }
    76         }
    77     }
    78 }

    结果为:

    其中代码的后半段的反射所使用的主要方法是 GetCustomAttributes,它返回对象数组,这些对象在运行时等效于源代码属性。

    2.线程与同步

    1)创建线程

    线程使程序在同一时间内做不同的事情。

    多处理器:快(同时进行)

    单处理器:慢(交替进行),来回切换

    下面创建了2个线程,分别从0数到1000和从1000数到0

     1 public static void Main ()
     2         {
     3             Tester t = new Tester();
     4             Console.WriteLine("let us begin the threading testing!");
     5             t.DoTest();
     6 
     7         }
     8         public void DoTest()
     9         {
    10             Thread t1 = new Thread(new ThreadStart(f1));
    11             Thread t2 = new Thread(new ThreadStart(f2));
    12             t1.Start();
    13             t2.Start();
    14         }
    15         public void f1()
    16         {
    17             for(int i = 0; i < 1000; i++)
    18             {
    19                 System.Console.WriteLine("f1:{0}", i);
    20             }
    21         }
    22         public void f2()
    23         {
    24             for (int i = 1000; i > 0; i--)
    25             {
    26                 System.Console.WriteLine("f2:{0}", i);
    27             }
    28         }

    结果为:可知,两个线程是交替进行的。

    2)拼接线程

    把t2.Join();写入t1的一个函数里,运行时t1将会挂起等待知道t2结束。

    3)通过睡眠阻塞线程

    加Thread.Sleep(),会让线程有机会在另一个线程打印一个值的时候运行。例如将1)中加入sleep,则结果变为:

    4)中断线程

    推荐的方法:设置布尔标记KeepAlive,线程间隔地检测这个值,当标记改变状态时,线程可以自己停止自己。

    (这是百度到的教程里的代码和讲解,感觉比课本里的清晰,但是好像用的是interrupt课本的略乱)

    代码中声明了两个线程,创建两线程的委托实例,例子是输出从1到50的整数,并在输出10,20和30之后使线程睡眠;输出从51到99的整数,并自动检测线程sleeper的状态,当sleeper处于WaitSleepJoin时,调用Interrupt使其回到调度队列:

     1 public class SleepAndInterrupt
     2 
     3 {
     4   //声明两线程
     5     public static Thread sleeper;
     6     public static Thread interrupter;
     7     public static void Main()
     8     {
     9         Console.WriteLine("进入Main");
    10         //创建两线程的委托实例
    11         sleeper = new Thread(new ThreadStart(SleepThread));
    12         interrupter = new Thread(new ThreadStart(InterruptThread));
    13         //开始执行两线程
    14       sleeper.Start();
    15         interrupter.Start();
    16         Console.WriteLine("退出Main");
    17     }
    18     //输出从1到50的整数,并在输出10,20和30之后使线程睡眠
    19     public static void SleepThread()
    20     {
    21         for(int i = 1; i <= 50; i++)
    22         {
    23            Console.Write (i+" ");
    24             if(i == 10 || i == 20 || i == 30)
    25             {
    26                 Console.WriteLine("在{0}处进入睡眠", i);
    27                 //捕捉使线程睡眠抛出的异常
    28                 try
    29                 {
    30                     Thread.Sleep(10);
    31                 }
    32                 catch
    33                 {
    34                 }
    35             }
    36         }
    37     }
    38     //输出从51到99的整数,并自动检测线程sleeper的状态
    39     //当sleeper处于WaitSleepJoin时,调用Interrupt使其回到调度队列
    40     public static void InterruptThread()
    41     {
    42         for(int i = 51; i < 100; i++)
    43         {
    44             Console.Write(i+" ");
    45             //判断线程sleeper的当前状态
    46             if(sleeper.ThreadState == System.Threading.ThreadState.WaitSleepJoin)
    47             {
    48                 Console.WriteLine("中断睡眠中的线程");
    49                 sleeper.Interrupt();
    50             }
    51         }
    52     }
    53 }

    结果为:

     5)同步

    同步通过对对象加锁实现,帮助程序员阻止另一个线程闯入你的对象,知道第一个线程不再使用这个对象为止。

    同步有三种方式:互锁类,c#lock语句,监控器器对象。

    首先模拟一个共享资源:

     1 namespace SharedResource
     2  {
     3      class Tester
     4      {
     5          private int counter = 0;
     6           static void Main()
     7          {
     8              Tester t = new Tester();
     9              t.DoTest();
    10          }
    11          public void DoTest()
    12           {
    13               Thread t1 = new Thread(new ThreadStart(f1));
    14               t1.IsBackground = true;
    15               t1.Name = "threadOne";
    16               t1.Start();
    17               Console.WriteLine("Started thread {0}", t1.Name);
    18               Thread t2 = new Thread(new ThreadStart(f1));
    19               t2.IsBackground = true;
    20               t2.Name = "threadOne";
    21               t2.Start();
    22               Console.WriteLine("Started thread {0}", t2.Name);
    23 
    24               t1.Join();
    25               t2.Join();
    26 
    27              //所有线程结束后打印一个消息
    28               Console.WriteLine("ALL thread are done.");
    29           }
    30          public void f1()
    31          {
    32              try
    33              {
    34                  while(counter < 1000)
    35                  {
    36                      int temp = counter;
    37                      temp++;
    38                      Thread.Sleep(1);
    39 
    40                      counter = temp;
    41                      Console.WriteLine("Thread {0}.f1:{1}", Thread.CurrentThread.Name, counter);
    42                  }
    43              }
    44              catch (ThreadInterruptedException)
    45              {
    46                  Console.WriteLine("thread{0} interrupted! Cleaning up...", Thread.CurrentThread.Name);
    47 
    48              }
    49              finally
    50              {
    51                  Console.WriteLine("Thread{0} existing.", Thread.CurrentThread.Name);
    52              }
    53          }
    54 
    55      }
    56  }

    结果为:(部分)

    然后使用互锁(Interlocked)

    改变上文中方法的try语句

    1              try
    2              {
    3                  while(counter < 1000)
    4                  {
    5                      int temp = Interlocked.Increment(ref counter);                  
    6                      Thread.Sleep(0);
    7                      Console.WriteLine("Thread {0}.f1:{1}", Thread.CurrentThread.Name, temp);
    8                  }
    9              }

    结果为(部分):

    此时对成员counter的访问就是同步的。

    然后是更广泛使用的同步机制c#lock,其可以控制对其他对象的访问,其标记了代码中的一个临界区,当锁有效的时候对指定的对象提供同步机制。

    将代码中try改为:

     1              try
     2              {
     3                  while(counter < 1000)
     4                  {
     5                      int temp;                  
     6                      Thread.Sleep(0);
     7                      lock(this)
     8                      {
     9                          temp = counter;
    10                          temp++;
    11                          Thread.Sleep(1);
    12                          counter = temp;
    13                      }
    14                      Console.WriteLine("Thread {0}.f1:{1}", Thread.CurrentThread.Name, temp);
    15                  }
    16              }

    输出与互锁相同。

    over

  • 相关阅读:
    不容易系列之(3)—— LELE的RPG难题(递推)
    亲和数(因子和)
    爬虫正式学习day2
    爬虫小练习:堆糖图片抓取--爬虫正式学习day1
    js笔记--高阶函数array的各种函数
    js笔记--高阶函数sort()
    js笔记--高阶函数filter()
    js笔记--高阶函数map() reduce()
    js笔记--方法
    js笔记--变量部分
  • 原文地址:https://www.cnblogs.com/3013218071zjr/p/4470352.html
Copyright © 2011-2022 走看看