友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第171章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




Thread。记住在实现Runnable 的时候,并没有实际产生一个 Thread 对象,只是一个拥有 run()方法的类。 

因此,我们必须明确地创建一个Thread 对象,并将 Runnable 对象传递给构建器,随后调用 start() (在构 

建器里进行)。在 CBox 里,这个线程的名字叫作 t。  

请留意数组 colors,它对 Color 类中的所有颜色进行了列举(枚举)。它在newColor()中用于产生一种随机 

选择的颜色。当前的单元(格)颜色是cColor。  

paint()则相当简单——只是将颜色设为cColor,然后用那种颜色填充整张画布(Canvas )。  

在run()中,我们看到一个无限循环,它将 cColor 设为一种随机颜色,然后调用 repaint()把它显示出来。 

随后,对线程执行 sleep(),使其“休眠”由命令行指定的时间长度。  

由于这种设计方案非常灵活,而且线程处理同每个Canvas 元素都紧密结合在一起,所以在理论上可以生成任 

意多的线程(但在实际应用中,这要受到JVM 能够从容对付的线程数量的限制)。  

这个程序也为我们提供了一个有趣的评测基准,因为它揭示了不同JVM 机制在速度上造成的戏剧性的差异。  



14。5。1 过多的线程  



有些时候,我们会发现ColorBoxes 几乎陷于停顿状态。在我自己的机器上,这一情况在产生了 10×10 的网 

格之后发生了。为什么会这样呢?自然地,我们有理由怀疑AWT 对它做了什么事情。所以这里有一个例子能 

够测试那个猜测,它产生了较少的线程。代码经过了重新组织,使一个Vector 实现了Runnable ,而且那个 

Vector 容纳了数量众多的色块,并随机挑选一些进行更新。随后,我们创建大量这些Vector 对象,数量大 

致取决于我们挑选的网格维数。结果便是我们得到比色块少得多的线程。所以假如有一个速度的加快,我们 

就能立即知道,因为前例的线程数量太多了。如下所示:  

  

//: ColorBoxes2。java  

// Balancing thread use  

import java。awt。*;  

import java。awt。event。*;  

import java。util。*;  

  

class CBox2 extends Canvas {  



                                                                                       532 


…………………………………………………………Page 534……………………………………………………………

  private static final Color'' colors = {   

    Color。black; Color。blue; Color。cyan;   

    Color。darkGray; Color。gray; Color。green;  

    Color。lightGray; Color。magenta;   

    Color。orange; Color。pink; Color。red;   

    Color。white; Color。yellow   

  };  

  private Color cColor = newColor();  

  private static final Color newColor() {  

    return colors'  

      (int)(Math。random() * colors。length)  

    ';  

  }  

  void nextColor() {  

    cColor = newColor();  

    repaint();  

  }  

  public void paint(Graphics  g) {  

    g。setColor(cColor);  

    Dimension s = getSize();  

    g。fillRect(0; 0; s。width; s。height);  

  }  

}  

  

class CBoxVector   

  extends Vector implements Runnable {  

  private Thread t;  

  private int pause;  

  public CBoxVector(int pause) {  

    this。pause = pause;  

    t = new Thread(this);  

  }  

  public void go() { t。start(); }  

  public void run() {  

    while(true) {  

      int i = (int)(Math。random() * size());  

      ((CBox2)elementAt(i))。nextColor();  

      try {  

        t。sleep(pause);  

      } catch(InterruptedException e) {}  

    }   

  }  

}  

  

public class ColorBoxes2 extends Frame {  

  private CBoxVector'' v;  

  public ColorBoxes2(int pause; int grid) {  

    setTitle(〃ColorBoxes2〃);  

    setLayout(new GridLayout(grid; grid));  

    v = new CBoxVector'grid';  

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

      v'i' = new CBoxVector(pause);  



                                                                                             533 


…………………………………………………………Page 535……………………………………………………………

    for (int i = 0; i 《 grid * grid; i++) {  

      v'i % grid'。addElement(new CBox2());  

      add((CBox2)v'i % grid'。lastElement());  

    }  

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

      v'i'。go();  

    addWindowListener(new WindowAdapter() {  

      public void windowClosing(WindowEvent e) {  

        System。exit(0);  

      }  

    });  

  }     

  public static void main(String'' args) {  

    // Shorter default pause than ColorBoxes:  

    int pause = 5;  

    int grid = 8;  

    if(args。length 》 0)   

      pause = Integer。parseInt(args'0');  

    if(args。length 》 1)  

      grid = Integer。parseInt(args'1');  

    Frame f = new ColorBoxes2(pause; grid);  

    f。setSize(500; 400);  

    f。setVisible(true);    

  }  

} ///:~  

  

在ColorBoxes2 中,我们创建了CBoxVector 的一个数组,并对其初始化,使其容下各个CBoxVector 网格。 

每个网格都知道自己该“睡眠”多长的时间。随后为每个 CBoxVector 都添加等量的 Cbox2 对象,而且将每个 

Vector 都告诉给 go(),用它来启动自己的线程。  

CBox2 类似CBox——能用一种随机选择的颜色描绘自己。但那就是 CBox2 能够做的全部工作。所有涉及线程 

的处理都已移至CBoxVector 进行。  

CBoxVector 也可以拥有继承的 Thread,并有一个类型为Vector 的成员对象。这样设计的好处就是 

addElement()和 elementAt()方法可以获得特定的参数以及返回值类型,而不是只能获得常规 Object (它们 

的名字也可以变得更短)。然而,这里采用的设计表面上看需要较少的代码。除此以外,它会自动保留一个 

Vector 的其他所有行为。由于 elementAt()需要大量进行“封闭”工作,用到许多括号,所以随着代码主体 

的扩充,最终仍有可能需要大量代码。  

和以前一样,在我们实现Runnable 的时候,并没有获得与 Thread 配套提供的所有功能,所以必须创建一个 

新的Thread,并将自己传递给它的构建器,以便正式“启动”——start()——一些东西。大家在 

CBoxVector 构建器和 go()里都可以体会到这一点。run()方法简单地选择Vector 里的一个随机元素编号,并 

为那个元素调用nextColor(),令其挑选一种新的随机颜色。  

运行这个程序时,大家会发现它确实变得更快,响应也更迅速(比如在中断它的时候,它能更快地停下 

来)。而且随着网格尺寸的壮大,它也不会经常性地陷于“停顿”状态。因此,线程的处理又多了一项新的 

考虑因素:必须随时检查自己有没有“太多的线程”(无论对什么程序和运行平台)。若线程太多,必须试 

着使用上面介绍的技术,对程序中的线程数量进行“平衡”。如果在一个多线程的程序中遇到了性能上的问 

题,那么现在有许多因素需要检查:  

(1) 对 sleep,yield()以及/或者wait()的调用足够多吗?  

(2) sleep()的调用时间足够长吗?  

(3) 运行的线程数是不是太多?  

(4) 试过不同的平台和 JVM 吗?  

象这样的一些问题是造成多线程应用程序的编制成为一种“技术活”的原因之一。  



                                                                                      534 


…………………………………………………………Page 536……………………………………………………………

14。6 总结  



何时使用多线程技术,以及何时避免用它,这是我们需要掌握的重要课题。骼它的主要目的是对大量任务进 

行有序的管理。通过多个任务的混合使用,可以更有效地利用计算机资源,或者对用户来说显得更方便。资 

源均衡的经典问题是在 IO等候期间如何利用 CPU。至于用户方面的方便性,最经典的问题就是如何在一个长 

时间的下载过程中监视并灵敏地反应一个“停止”(stop )按钮的按下。  

多线程的主要缺点包括:  

(1) 等候使用共享资源时造成程序的运行速度变慢。  

(2) 对线程进行管理要求的额外CPU 开销。  

(3) 复杂程度无意义的加大,比如用独立的线程来更新数组内每个元素的愚蠢主意。  

(4) 漫长的等待、浪费精力的资源竞争以及死锁等多线程症状。  

线程另一个优点是它们用“轻度”执行切换(100条指令的顺序)取代了“重度”进程场景切换(1000 条指 

令)。由于一个进程内的所有线程共享相同的内存空间,所以“轻度”场景切换只改变程序的执行和本地变 

量。而在“重度”场景切换时,一个进程的改变要求必须完整地交换内存空间。  

线程处理看来好象进入了一个全新的领域,似乎要求我们学习一种全新的程序设计语言——或者至少学习一 

系列新的语言概念。由于大多数微机操作系统都提供了对线程的支持,所以程序设计语言或者库里也出现了 

对线程的扩展。不管在什么情况下,涉及线程的程序设计:  

(1) 刚开始会让人摸不着头脑,要求改换我们传统的编程思路;  

(2) 其他语言对线程的支持看来是类似的。所以一旦掌握了线程的概念,在其他环境也不会有太大的困难。 

尽管对线程的支持使Java 语言的复杂程度多少有些增加,但请不要责怪 Java 。毕竟,利用线程可以做许多 

有益的事情。  

多个线程可能共享同一个资源(比如一个对象里的内存),这是运用线程时面临的最大的一个麻烦。必须保 

证多个线程不会同时试图读取和修改那个资源。这要求技巧性地运用 synchronized (同步)关键字。它是一 

个有用的工具,但必须真正掌握它,因为假若操作不当,极易出现死锁。  

除此以外,运用线程时还要注意一个非常特殊的问题。由于根据Java 的设计,它允许我们根据需要创建任意 

数量的线程——至少理论上如此(例如
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!