最近需要解决一个多线程问题,将这个问题抽象说来就是这个情况。

有A B两个方法同时完成F工作,A B操作均比较耗时,且 B操作需要A操作完成后才能执行。

现 要 A 和B同时运行n个线程。

用数学化的语言描述一下

/***************************
* 现有线程 A1,A2……Ai……Ak
* 线程B1,B2,B3……Bi……Bk
* Ai和Bi需要顺序执行,共同完成F操作
* Ai和Bi+1之间无干扰
* Bi和Bi+1之间无干扰
* Ai和Bi+1之间无干扰
* A B操作都比较耗时
************************/

 

最初在思考解决方案的时候,想的是 为每一A设置一个标记位,去记录 当前的Ai所处的状态,然后再Bi中去循环访问Ai的该标记,如果标记表示可执行Bi,则跳出循环,执行Bi操作。

想来这种方案应该也能实现,但又想到C#提供的Join方法,刚好就是解决t2线程运行前需要等待t1完成的问题而给出的,恰好可以利用,处理起来应该会更简单,更安全。

Join方法是指将指定的线程合并到当前线程中,最初学的时候很不清楚这个合并是什么意思,现在看来应该就是 类似与在 原有的t2一块木板(当前线程)上的某个位置出 拼上 t1木板(指定线程),这样,运行t2木板是,合并上的t1那一块也就成为了必经的路程。

Join方法还提供了Join的时间,以免 t1操作过久,导致一直等待下去。如 t2.Join(100);

考虑上面的问题,由于 Ai和Bi 之间才有同步关系,所以 需要处理就是这一个对应,Join的时候只要找到Bi对应的Ai线程即可

故,我为在整个类中保存两个了静态的 字典 Dictionary<int,Thread> 前一个 表示该线程的索引,=后一个表示该线程本身

源代码如下:


        public   class   AiBiThread
        {
                // 保存A的所有线程   索引,线程对象
                static   Dictionary < int,Thread >   TADic = new   Dictionary < int,Thread > ( ) ;
                // 保存A的所有线程   索引,线程对象
                static   Dictionary < int,   Thread >   TBDic   =   new   Dictionary < int,   Thread > ( ) ;

                public     void   Start ( )
10                 {
11                         // 创建多个A线程
12                         for ( int   i = 0 ;i &lt; 20;i + + )
13                         {
14                                 Thread   tA = new   Thread ( A ) ;
15                                 TADic . Add ( i,tA ) ;
16                                 tA . Start ( i ) ; // 传入线程索引
17                         }
18
19                         // 创建多个B线程
20                         for   ( int   i   =   0 ;   i   &lt;   20 ;   i + + )
21                         {
22                                 Thread   tB   =   new   Thread ( B ) ;
23                                 TBDic . Add ( i,tB ) ;
24                                 tB . Start ( i ) ; // 传入线程索引
25                         }
26                         Console . ReadLine ( ) ;
27                 }
28
29                 public     void   A ( object     i )
30                 {
31                         Console . WriteLine ( " 进入线程A-- " + i ) ;
32                         Console . WriteLine ( " 线程A-- "   +   i + " 正在运行 " ) ;
33                         Thread . Sleep ( 100 ) ; // 模拟A的耗时,使A停顿大于B,保证进入B时,相应的A尚未运行完毕
34                         Console . WriteLine ( " 线程A-- " + i + " 要结束了 " ) ;
35                 }
36
37                 public   void   B ( object     i )
38                 {
39                           Console . WriteLine ( " 进入线程B-- "   +   i ) ;
40                             int   taIndex   =   ( int )   i;
41                             Console . WriteLine ( " 正在等待线程A-- "   +   i ) ;
42                             TADic [ taIndex ] . Join ( ) ; // 对相应的A进行Join
43                             Console . WriteLine ( " 等待线程A-- "   +   i + " 等待完毕!! " ) ;
44                      
45                         Console . WriteLine ( " 线程B-- "   +   i   +   " 继续运行 " ) ;
46                         Thread . Sleep ( 50 ) ; // 模拟B的耗时操作
47                         Console . WriteLine ( " 线程B-- "   +   i   +   " 要结束了 " ) ;
48                 }
49         }

然后再Main中调用Start方法,整个模拟完毕,输出结果如下:

进入线程A--0
进入线程A--1
线程A--1正在运行
进入线程A--2
线程A--2正在运行
进入线程A--3
线程A--3正在运行
进入线程A--4
线程A--4正在运行
线程A--0正在运行
进入线程A--5
线程A--5正在运行
进入线程A--6
线程A--6正在运行
进入线程A--7
线程A--7正在运行
进入线程A--8
线程A--8正在运行
进入线程A--9
线程A--9正在运行
进入线程A--10
线程A--10正在运行
进入线程A--11
线程A--11正在运行
进入线程A--12
线程A--12正在运行
进入线程A--13
线程A--13正在运行
进入线程A--14
线程A--14正在运行
进入线程A--15
线程A--15正在运行
进入线程A--16
线程A--16正在运行
进入线程A--17
线程A--17正在运行
进入线程A--18
线程A--18正在运行
进入线程A--19
线程A--19正在运行
进入线程B--0
正在等待线程A--0
进入线程B--1
正在等待线程A--1
进入线程B--2
正在等待线程A--2
进入线程B--3
正在等待线程A--3
进入线程B--4
正在等待线程A--4
进入线程B--5
正在等待线程A--5
进入线程B--6
正在等待线程A--6
进入线程B--7
进入线程B--8
正在等待线程A--8
正在等待线程A--7
进入线程B--9
正在等待线程A--9
进入线程B--10
正在等待线程A--10
进入线程B--12
正在等待线程A--12
进入线程B--11
进入线程B--13
正在等待线程A--13
进入线程B--15
正在等待线程A--15
进入线程B--14
正在等待线程A--14
进入线程B--16
正在等待线程A--11
正在等待线程A--16
进入线程B--18
正在等待线程A--18
进入线程B--17
进入线程B--19
正在等待线程A--17
正在等待线程A--19
线程A--2要结束了
等待线程A--2等待完毕!!
线程B--2继续运行
线程A--1要结束了
线程A--0要结束了
线程A--8要结束了
线程A--10要结束了
线程A--4要结束了
线程A--11要结束了
线程A--6要结束了
等待线程A--0等待完毕!!
等待线程A--8等待完毕!!
线程A--12要结束了
等待线程A--10等待完毕!!
等待线程A--4等待完毕!!
线程A--14要结束了
线程A--3要结束了
线程A--7要结束了
线程A--5要结束了
等待线程A--1等待完毕!!
线程A--9要结束了
线程A--13要结束了
线程A--15要结束了
线程A--17要结束了
等待线程A--11等待完毕!!
线程A--16要结束了
等待线程A--6等待完毕!!
线程B--0继续运行
线程A--18要结束了
线程B--8继续运行
等待线程A--12等待完毕!!
线程B--10继续运行
线程B--4继续运行
等待线程A--14等待完毕!!
线程A--19要结束了
等待线程A--3等待完毕!!
等待线程A--7等待完毕!!
等待线程A--5等待完毕!!
线程B--1继续运行
等待线程A--9等待完毕!!
线程B--11继续运行
等待线程A--13等待完毕!!
等待线程A--15等待完毕!!
等待线程A--17等待完毕!!
等待线程A--16等待完毕!!
线程B--6继续运行
等待线程A--18等待完毕!!
线程B--2要结束了
线程B--12继续运行
线程B--14继续运行
等待线程A--19等待完毕!!
线程B--3继续运行
线程B--7继续运行
线程B--5继续运行
线程B--9继续运行
线程B--13继续运行
线程B--15继续运行
线程B--17继续运行
线程B--16继续运行
线程B--18继续运行
线程B--19继续运行
线程B--0要结束了
线程B--8要结束了
线程B--10要结束了
线程B--4要结束了
线程B--1要结束了
线程B--11要结束了
线程B--6要结束了
线程B--12要结束了
线程B--14要结束了
线程B--3要结束了
线程B--7要结束了
线程B--5要结束了
线程B--9要结束了
线程B--13要结束了
线程B--17要结束了
线程B--15要结束了
线程B--19要结束了
线程B--16要结束了
线程B--18要结束了

 

验证 原来提出的要求

1. Ai和Bi需要顺序执行

     查看A2和B2的运行过程情况 依次是 
      进入线程A—2    线程A--2正在运行   进入线程B—2  正在等待线程A—2  线程A--2要结束了     等待线程A--2等待完毕!!   线程B--2继续运行    线程B--2要结束了

    验证通过

2. Ai 和Bi+1 无干扰

    查看 A4 和B 5 状态,二者之间无干扰

3.Ai 和Ai+1无干扰,查看 A9 和A 8 状态

4.Bi 和Bi+1无干扰,查看 B9 和B 8 状态

备注 :(其实严格说来 2,3,4 通过这一组数据是得不出这样的结果的,应该是多组数据进行观察。上述234结论只能说是理论分析得来。)

原问题顺利解决。

线程中的Join的问题就暂时说到这里。

 

                                                                          Created by Web~CJT眨眼