在作者機器上,ColorBoxes 產生 10×10 網格後幾乎陷入停頓。懷疑 AWT 做了什麼事。以下範例測試此猜測,產生較少執行緒:將程式碼重組,讓 Vector 實作 Runnable,容納大量色塊並隨機挑選更新。建立大量 Vector 物件,數量約等於網格維度。結果:執行緒遠少於色塊數。若速度變快,證實前例執行緒過多。
//: ColorBoxes2.java
import java.awt.*;
import java.awt.event.*;
import java.util.*;
class CBox2 extends Canvas {
private static final Color[] colors = { /* 13 種顏色 */ };
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);
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) {
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);
}
} ///:~
Vector 實作 Runnable,所有執行緒處理移至此處。run() 隨機選擇 Vector 元素呼叫 nextColor()CBoxVector 陣列,每個網格知道睡眠時間。為每個 Vector 添加等量 CBox2,啟動各自執行緒運行發現:確實更快、回應更迅速(中斷時能更快停下)。隨網格尺寸增大,不會頻繁陷入「停頓」。
新考慮因素:必須隨時檢查是否有「太多執行緒」(視程式與平台)。若過多,嘗試上述技術「平衡」執行緒數量。遇到多執行緒效能問題時檢查:
sleep、yield()、wait() 呼叫是否足夠?sleep() 時間是否足夠長?這些問題正是多執行緒應用程式編寫成為「技術活」的原因之一。