看了Thinking in java上的多线程后颇有感触,著文记之。在这里我假设各位都已经拥有了awt和applet的初级知识。
所谓线程,即计算机进程内部的子执行模块,从具体表现上来说,就是独立分配到一部分系统资源而独立于其他可执行代码执行的可执行代码。在java中,实现了语言上的多线程编程。Thinking in java中举了一系列的几个例子来阐述其较为表层的特点。
对于一个拥有ui的程序来说,控制其ui的代码段一般运行在一个线程中,如果想要时刻刷新ui中某些控件的外观,则最好在另一个线程中进行操作,否则可能导致ui线程的阻塞,从而让用户感觉到应用程序停止了交互(例如点击按钮没有了反应等)。例如下面这个取自Thinking in java的计时器案例:
1 package com.william.myclient; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.applet.*; 6 7 public class Counter1 extends Applet { 8 9 private int count = 0; 10 private Button onOff = new Button("Toggle"), start = new Button("Start"); 11 private TextField t = new TextField(10); 12 private boolean runFlag = true; 13 14 public void init() { 15 add(t); 16 start.addActionListener(new StartL()); 17 add(start); 18 onOff.addActionListener(new OnOffL()); 19 add(onOff); 20 } 21 22 public void go() { 23 while (true) { 24 try { 25 Thread.currentThread().sleep(100); 26 } 27 catch (InterruptedException e) { 28 29 } 30 if (runFlag) 31 t.setText(Integer.toString(count++)); 32 } 33 } 34 35 class StartL implements ActionListener { 36 public void actionPerformed(ActionEvent e) { 37 go(); 38 } 39 } 40 41 class OnOffL implements ActionListener { 42 public void actionPerformed(ActionEvent e) { 43 runFlag = !runFlag; 44 } 45 } 46 47 public static void main(String[] args) { 48 Counter1 applet = new Counter1(); 49 Frame aFrame = new Frame("Counter1"); 50 aFrame.addWindowListener(new WindowAdapter() { 51 public void windowClosing(WindowEvent e) { 52 System.exit(0); 53 } 54 }); 55 aFrame.add(applet, BorderLayout.CENTER); 56 aFrame.setSize(300, 200); 57 applet.init(); 58 applet.start(); 59 aFrame.setVisible(true); 60 } 61 }
紧接下来请看如下代码:
1 package com.william.myclient; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.applet.*; 6 7 class SeparateSubTask extends Thread { 8 private int count = 0; 9 private Counter2 c2; 10 private boolean runFlag = true; 11 12 public SeparateSubTask(Counter2 c2) { 13 this.c2 = c2; 14 start(); 15 } 16 17 public void invertFlag() { 18 runFlag = !runFlag; 19 } 20 21 public void run() { 22 while (true) { 23 try { 24 sleep(100); 25 } 26 catch (InterruptedException e) { 27 28 } 29 if (runFlag) 30 c2.t.setText(Integer.toString(count++)); 31 } 32 } 33 } 34 35 public class Counter2 extends Applet { 36 TextField t = new TextField(10); 37 private SeparateSubTask sp = null; 38 private Button onOff = new Button("Toggle"), start = new Button("Start"); 39 40 public void init() { 41 add(t); 42 start.addActionListener(new StartL()); 43 add(start); 44 onOff.addActionListener(new OnOffL()); 45 add(onOff); 46 } 47 48 class StartL implements ActionListener { 49 public void actionPerformed(ActionEvent e) { 50 if (sp == null) 51 sp = new SeparateSubTask(Counter2.this); 52 } 53 } 54 55 class OnOffL implements ActionListener { 56 public void actionPerformed(ActionEvent e) { 57 if (sp != null) 58 sp.invertFlag(); 59 } 60 } 61 62 public static void main(String[] args) { 63 Counter2 applet = new Counter2(); 64 Frame aFrame = new Frame("Counter2"); 65 aFrame.addWindowListener(new WindowAdapter() { 66 public void windowClosing(WindowEvent e) { 67 System.exit(0); 68 } 69 }); 70 aFrame.add(applet, BorderLayout.CENTER); 71 aFrame.setSize(300, 200); 72 applet.init(); 73 applet.start(); 74 aFrame.setVisible(true); 75 } 76 }
1 package com.william.myclient; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.applet.*; 6 7 public class Counter2i extends Applet { 8 private class SeparateSubTask extends Thread { 9 int count = 0; 10 boolean runFlag = true; 11 12 SeparateSubTask() { 13 start(); 14 } 15 16 public void run() { 17 while (true) { 18 try { 19 sleep(100); 20 } catch (InterruptedException e) { 21 22 } 23 if (runFlag) 24 t.setText(Integer.toString(count++)); 25 } 26 } 27 } 28 29 private SeparateSubTask sp = null; 30 private TextField t = new TextField(10); 31 private Button onOff = new Button("Toggle"), start = new Button("Start"); 32 33 public void init() { 34 add(t); 35 start.addActionListener(new StartL()); 36 add(start); 37 onOff.addActionListener(new OnOffL()); 38 add(onOff); 39 } 40 41 class StartL implements ActionListener { 42 public void actionPerformed(ActionEvent e) { 43 if (sp == null) 44 sp = new SeparateSubTask(); 45 } 46 } 47 48 class OnOffL implements ActionListener { 49 public void actionPerformed(ActionEvent e) { 50 if (sp != null) 51 sp.runFlag = !sp.runFlag; // invertFlag(); 52 } 53 } 54 55 public static void main(String[] args) { 56 Counter2i applet = new Counter2i(); 57 Frame aFrame = new Frame("Counter2i"); 58 aFrame.addWindowListener(new WindowAdapter() { 59 public void windowClosing(WindowEvent e) { 60 System.exit(0); 61 } 62 }); 63 aFrame.add(applet, BorderLayout.CENTER); 64 aFrame.setSize(300, 200); 65 applet.init(); 66 applet.start(); 67 aFrame.setVisible(true); 68 } 69 } 70
实现代码如下:
1 package com.william.myclient; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.applet.*; 6 7 public class Counter3 extends Applet implements Runnable { 8 private int count = 0; 9 private boolean runFlag = true; 10 private Thread selfThread = null; 11 private Button onOff = new Button("Toggle"), start = new Button("Start"); 12 private TextField t = new TextField(10); 13 14 public void init() { 15 add(t); 16 start.addActionListener(new StartL()); 17 add(start); 18 onOff.addActionListener(new OnOffL()); 19 add(onOff); 20 } 21 22 public void run() { 23 while (true) { 24 try { 25 selfThread.sleep(100); 26 } catch (InterruptedException e) { 27 } 28 if (runFlag) 29 t.setText(Integer.toString(count++)); 30 } 31 } 32 33 class StartL implements ActionListener { 34 public void actionPerformed(ActionEvent e) { 35 if (selfThread == null) { 36 selfThread = new Thread(Counter3.this); 37 selfThread.start(); 38 } 39 } 40 } 41 42 class OnOffL implements ActionListener { 43 public void actionPerformed(ActionEvent e) { 44 runFlag = !runFlag; 45 } 46 } 47 48 public static void main(String[] args) { 49 Counter3 applet = new Counter3(); 50 Frame aFrame = new Frame("Counter3"); 51 aFrame.addWindowListener(new WindowAdapter() { 52 public void windowClosing(WindowEvent e) { 53 System.exit(0); 54 } 55 }); 56 aFrame.add(applet, BorderLayout.CENTER); 57 aFrame.setSize(300, 200); 58 applet.init(); 59 applet.start(); 60 aFrame.setVisible(true); 61 } 62 } 63
1 package com.william.myclient; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.applet.*; 6 7 class Ticker extends Thread { 8 private Button b = new Button("Toggle"); 9 private TextField t = new TextField(10); 10 private int count = 0; 11 private boolean runFlag = true; 12 13 public Ticker(Container c) { 14 b.addActionListener(new ToggleL()); 15 Panel p = new Panel(); 16 p.add(t); 17 p.add(b); 18 c.add(p); 19 } 20 21 class ToggleL implements ActionListener { 22 public void actionPerformed(ActionEvent e) { 23 runFlag = !runFlag; 24 } 25 } 26 27 public void run() { 28 while (true) { 29 if (runFlag) 30 t.setText(Integer.toString(count++)); 31 try { 32 sleep(100); 33 } catch (InterruptedException e) { 34 } 35 } 36 } 37 } 38 39 public class Counter4 extends Applet { 40 private Button start = new Button("Start"); 41 private boolean started = false; 42 private Ticker[] s; 43 private boolean isApplet = true; 44 private int size; 45 46 public void init() { 47 // Get parameter "size" from Web page: 48 if (isApplet) 49 size = Integer.parseInt(getParameter("size")); 50 s = new Ticker[size]; 51 for (int i = 0; i < s.length; i++) 52 s[i] = new Ticker(this); 53 start.addActionListener(new StartL()); 54 add(start); 55 } 56 57 class StartL implements ActionListener { 58 public void actionPerformed(ActionEvent e) { 59 if (!started) { 60 started = true; 61 for (int i = 0; i < s.length; i++) 62 s[i].start(); 63 } 64 } 65 } 66 67 public static void main(String[] args) { 68 Counter4 applet = new Counter4(); 69 // This isn't an applet, so set the flag and 70 // produce the parameter values from args: 71 applet.isApplet = false; 72 applet.size = (args.length == 0 ? 5 : Integer.parseInt(args[0])); 73 Frame aFrame = new Frame("Counter4"); 74 aFrame.addWindowListener(new WindowAdapter() { 75 public void windowClosing(WindowEvent e) { 76 System.exit(0); 77 } 78 }); 79 aFrame.add(applet, BorderLayout.CENTER); 80 aFrame.setSize(200, applet.size * 50); 81 applet.init(); 82 applet.start(); 83 aFrame.setVisible(true); 84 } 85 } 86
好啦,就到这里吧。过年了,大年初一写了这篇博文。在这里祝大家兔年吉祥咯!