友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
第三电子书 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

Java编程思想第4版[中文版](PDF格式)-第123部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!


段,用于显示线程组的最大优先级(在下一节里,我们将全面讨论线程组的问题)。最后,父线程组的优先 

级也作为标签显示出来。  

按下“up”(上)或“down”(下)按钮的时候,会先取得Ticker2 当前的优先级,然后相应地提高或者降 

低。  

运行该程序时,我们可注意到几件事情。首先,线程组的默认优先级是5。即使在启动线程之前(或者在创 

建线程之前,这要求对代码进行适当的修改)将最大优先级降到5 以下,每个线程都会有一个5 的默认优先 

级。  



                                                                                          524 


…………………………………………………………Page 526……………………………………………………………

最简单的测试是获取一个计数器,将它的优先级降低至 1,此时应观察到它的计数频率显著放慢。现在试着 

再次提高优先级,可以升高回线程组的优先级,但不能再高了。现在将线程组的优先级降低两次。线程的优 

先级不会改变,但假若试图提高或者降低它,就会发现这个优先级自动变成线程组的优先级。此外,新线程 

仍然具有一个默认优先级,即使它比组的优先级还要高(换句话说,不要指望利用组优先级来防止新线程拥 

有比现有的更高的优先级)。  

最后,试着提高组的最大优先级。可以发现,这样做是没有效果的。我们只能减少线程组的最大优先级,而 

不能增大它。  



14。4。1 线程组  



所有线程都隶属于一个线程组。那可以是一个默认线程组,亦可是一个创建线程时明确指定的组。在创建之 

初,线程被限制到一个组里,而且不能改变到一个不同的组。每个应用都至少有一个线程从属于系统线程 

组。若创建多个线程而不指定一个组,它们就会自动归属于系统线程组。  

线程组也必须从属于其他线程组。必须在构建器里指定新线程组从属于哪个线程组。若在创建一个线程组的 

时候没有指定它的归属,则同样会自动成为系统线程组的一名属下。因此,一个应用程序中的所有线程组最 

终都会将系统线程组作为自己的“父”。  

之所以要提出“线程组”的概念,很难从字面上找到原因。这多少为我们讨论的主题带来了一些混乱。一般 

地说,我们认为是由于“安全”或者“保密”方面的理由才使用线程组的。根据 Arnold 和 Gosling 的说法: 

 “线程组中的线程可以修改组内的其他线程,包括那些位于分层结构最深处的。一个线程不能修改位于自己 

所在组或者下属组之外的任何线程”(注释①)。然而,我们很难判断“修改”在这儿的具体含义是什么。 

下面这个例子展示了位于一个“叶子组”内的线程能修改它所在线程组树的所有线程的优先级,同时还能为 

这个“树”内的所有线程都调用一个方法。  

  

①:《The Java Programming Language》第 179 页。该书由 Arnold 和 Jams Gosling 编著,Addison…Wesley 

于 1996 年出版  

  

//: TestAccess。java  

// How threads can access other threads  

// in a parent thread group  

  

public class TestAccess {  

  public static void main(String'' args) {  

    ThreadGroup   

      x = new ThreadGroup(〃x〃);  

      y = new ThreadGroup(x; 〃y〃);  

      z = new ThreadGroup(y; 〃z〃);  

    Thread  

      one = new TestThread1(x; 〃one〃);  

      two = new TestThread2(z; 〃two〃);  

  }  

}  

  

class TestThread1 extends Thread {  

  private int i;  

  TestThread1(ThreadGroup g; String name) {  

    super(g; name);  

  }  

  void f() {  

    i++; // modify this thread  

    System。out。println(getName() + 〃 f()〃);  

  }  

}  

  



                                                                                     525 


…………………………………………………………Page 527……………………………………………………………

class TestThread2 extends TestThread1 {  

  TestThread2(ThreadGroup g; String name) {  

    super(g; name);  

    start();  

  }  

  public void run() {  

    ThreadGroup g =  

      getThreadGroup()。getParent()。getParent();  

    g。list();  

    Thread'' gAll = new Thread'g。act iveCount()';  

    g。enumerate(gAll);  

    for(int i = 0; i 《 gAll。length; i++) {  

      gAll'i'。setPriority(Thread。MIN_PRIORITY);  

      ((TestThread1)gAll'i')。f();  

    }  

    g。list();  

  }  

} ///:~  

  

在main()中,我们创建了几个ThreadGroup (线程组),每个都位于不同的“叶”上:x 没有参数,只有它 

的名字(一个String),所以会自动进入“system”(系统)线程组;y 位于x 下方,而 z位于y 下方。注 

意初始化是按照文字顺序进行的,所以代码合法。  

有两个线程创建之后进入了不同的线程组。其中,TestThread1 没有一个 run()方法,但有一个f(),用于通 

知线程以及打印出一些东西,以便我们知道它已被调用。而TestThread2 属于TestThread1 的一个子类,它 

的run()非常详尽,要做许多事情。首先,它获得当前线程所在的线程组,然后利用getParent()在继承树中 

向上移动两级(这样做是有道理的,因为我想把TestThread2 在分级结构中向下移动两级)。随后,我们调 

用方法 activeCount() ,查询这个线程组以及所有子线程组内有多少个线程,从而创建由指向Thread 的句柄 

构成的一个数组。enumerate()方法将指向所有这些线程的句柄置入数组 gAll 里。然后在整个数组里遍历, 

为每个线程都调用 f()方法,同时修改优先级。这样一来,位于一个“叶子”线程组里的线程就修改了位于 

父线程组的线程。  

调试方法 list()打印出与一个线程组有关的所有信息,把它们作为标准输出。在我们对线程组的行为进行调 

查的时候,这样做是相当有好处的。下面是程序的输出:  

  

java。lang。ThreadGroup'name=x;maxpri=10'  

    Thread'one;5;x'  

    java。lang。ThreadGroup'name=y;maxpri=10'  

        java。lang。ThreadGroup'name=z;maxpri=10'  

            Thread'two;5;z'  

one f()  

two f()  

java。lang。ThreadGroup'name=x;maxpri=10'  

    Thread'one;1;x'  

    java。lang。ThreadGroup'name=y;maxpri=10'  

        java。lang。ThreadGroup'name=z;maxpri=10'  

            Thread'two;1;z'  

  

list()不仅打印出 ThreadGroup 或者Thread 的类名,也打印出了线程组的名字以及它的最高优先级。对于线 

程,则打印出它们的名字,并接上线程优先级以及所属的线程组。注意 list()会对线程和线程组进行缩排处 

理,指出它们是未缩排的线程组的“子”。  

大家可看到 f()是由TestThread2 的run()方法调用的,所以很明显,组内的所有线程都是相当脆弱的。然 

而,我们只能访问那些从自己的system 线程组树分支出来的线程,而且或许这就是所谓“安全”的意思。我 

们不能访问其他任何人的系统线程树。  



                                                                                         526 


…………………………………………………………Page 528……………………………………………………………

  

1。 线程组的控制  

抛开安全问题不谈,线程组最有用的一个地方就是控制:只需用单个命令即可完成对整个线程组的操作。下 

面这个例子演示了这一点,并对线程组内优先级的限制进行了说明。括号内的注释数字便于大家比较输出结 

果:  

  

//: ThreadGroup1。java  

// How thread groups control priorities  

// of the threads inside them。  

  

public class ThreadGroup1 {  

  public static void main(String'' args) {  

    // Get the system thread & print its Info:  

    ThreadGroup sys =   

      Thread。currentThread()。getThreadGroup();  

    sys。list(); // (1)  

    // Reduce the system thread group priority:  

    sys。setMaxPriority(Thread。MAX_PRIORITY 1);  

    // Increase the main thread priority:  

    Thread curr = Thread。currentThread();  

    curr。setPriority(curr。getPriority() + 1);  

    sys。list(); // (2)  

    // Attempt to set a new group to the max:  

    ThreadGroup g1 = new ThreadGroup(〃g1〃);  

    g1。setMaxPriority(Thread。MAX_PRIORITY);  

    // Attempt to set a new thread to the max:  

    Thread t = new Thread(g1; 〃A〃);  

    t。setPriority(Thread。MAX_PRIORITY);  

    g1。list(); // (3)  

    // Reduce g1's max priority; then attempt  

    // to increase it:  

    g1。setMaxPriority(Thread。MAX_PRIORITY 2);  

    g1。setMaxPriority(Thread。MAX_PRIORITY);  

    g1。list(); // (4)  

    // Attempt to set a new thread to the max:  

    t = new Thread(g1; 〃B〃);  

    t。setPriority(Thread。MAX_PRIORITY);  

    g1。list(); // (5)  

    // Lower the max priority below the default  

    // thread priority:  

    g1。setMaxPriority(Thread。MIN_PRIORITY + 2);  

    // Look at a new thread's priority before  

    // and after changing it:  

    t = new Thread(g1; 〃C〃);  

    g1。list(); // (6)  

    t。setPriority(t。getPriority() …1);  

    g1。list(); // (7)  

    // Make g2 a child Threadgroup of g1 and  

    // try to increase its priority:  

    ThreadGroup g2 = new ThreadGroup(g1; 〃g2〃);  

    g2。list(); // (8)  

    g2。setMaxPriority(Thread。MAX_PRIORITY);  



                                                                                          527 


…………………………………………………………Page 529……………………………………………………………

    g2。list(); // (9)  

    // Add a bunch of new threads to g2:  

    for (int i = 0; i 《 5; i++)  

      new Thread(g2; Integer。toString(i));  

    // Show information about all threadgroups  

    // and threads:  

    sys。list(); // (10)  

    System。out。println(〃Starting all threads:〃);  

    Thread'' all = new Thread'sys。activeCount()';  

    sys。enumerate(all);  

    for(int i = 0; i 《 all。length; i++)  

      if(!all'i'。isAlive())  

        all'i'。start();  

    // Suspends & Stops all threads in   

    // this group and its subgroups:  

    System。out。println(〃All threads started〃);  

    sys。suspend(); // Deprecated in Java 1。2  

    // Never gets here。。。  

    System。out。println(〃All threads suspended〃);  

    sys。stop(); // Deprecated in Java 1。2  

    System。out。println(〃All threads stopped〃);  

  }  

} ///:~  

  

下面的输出结果已进行了适当的编辑,以便用一页能够装下(java。lang。已被删去),而且添加了适当的数 

字,与前面程序列表中括号里的数字对应:  

  

(1) ThreadGroup'name=system;maxpri=10'  

      Thread'main;5;system'  

(2) ThreadGroup'name=system;maxpri=9'  

      Thread'main;6;system'  

(3) ThreadGroup'name=g1;maxpri=9'  

      Thread'A;9;g1'  

(4) ThreadGroup'name=g1;maxpri=8'  

      Thread'A;9;g 1'  

(5) ThreadGroup'name=g1;maxpri=8'  

      Thread'A;9;g1'  

      Thread'B;8;g1'  

(6) ThreadGroup'name=g1;maxpri=3'  

      Thread'A;9;g1'  

      Thread'B;8;g1'  

      Thread'C;6;g1'  

(7) ThreadGroup'name=g1;maxpri=3'  

      Thread'A;9;g1'  

      Thread'B;8;g1'  

      Thread'C;3;g1'  

(8) ThreadGroup'name=g2;maxpri=3'  

(9) ThreadGroup'name=g2;maxpri=3'  

(10)ThreadGroup'name=system;maxpri=9'  

      Thread'main;6;system'  

      ThreadGroup'name=g1;maxpri=3'  

        Thread'A;9;g1'  



                                                                                           528 


…………………………………………………………Page 530……………………………………………………………

        Thread'B;8;g1'  

        Thread'C;3;g1'  

        ThreadGroup'name=g2;maxpri=3'  

          Thread'0;6;g2'  

          Thread'1;6;g2'  

          Thread'2;6;g2'  

          Thread'3;6;g2'  

          Thread'4;6;g2'  

Starting all threads:  

All threads started  

  

所有程序都至少有一个线程在运行,而且 main()采取的第一项行动便是调用Thread 的一个static (静态) 

方法,名为 currentThread()。从这个线程开始,线程组将被创建,而且会为结果调用 list()。输出如下:  

  

(1) ThreadGroup'name=system;maxpri=10'  

      Thread'main;5;system'  

  

我们可以看到,主线程组的名字是 system,而主线程的名字是main ,而且它从属于system线程组。  

第二个练习显示出 system 组的最高优先级可以减少,而且main 线程可以增大自己的优先级:  

  

(2) ThreadGroup'name=system;maxpri=9'  

      Thread'main;6;system'  

  

第三个练习创建一个新的线程组,名为g1;它自动从属于system 线程组,因为并没有明确指定它的归属关 

系。我们在 g1 内部放置了一个新线程,名为A 。随后,我
返回目录 上一页 下一页 回到顶部 1 1
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!