标签:
“多线程最主要的一个用途是构建一个”反应灵敏“的界面”
--摘自《Java编程思想》
为了理解上面这句话,我们可以假设一种情景:假设有一个程序,该程序用来处理大量的数学运算,在多数情况下会占用大量的cpu时间,
而在处理数据的过程中又尝尝需要与用户进行交互,而如果进程中只有一个主线程的话,那么程序每次都需要等到该主线程的任务完成后
才能对界面操作进行响应,这在通常的情况下是不可接受的。我们可以设想一个情景就是在程序运行时,如果突然有事需要离开(导师请你
出去吃饭,机会难得),这时你可能就需要点击关闭按钮,关闭程序,但是程序却说我这还有200次循环要跑,没空理你,等会我。如果遇到这种
情况,我们也有办法,打开任务管理器,结束进程,简单有效但是却很暴力。
接下来我们会举两个例子,一个是单线程对界面反应迟钝的例子,一个是多线程(双线程)对界面反应灵活的例子。
程序界面为下图,大致流程是当我们点击start按钮后,程序从0开始自增计数,并把结果显示在输入框中,而当我们点击Toggle按钮时,计数暂停,
再次点击计数恢复。
为了体现单线程与多线程的差异,我们把这个计数的过程定义为一个死循环,即从0自增到无穷大,而Toggle按钮则可以用来暂停这个循环。在例子一中
只有一个主线程,这就导致在计数循环时,程序不能够对点击按钮的操作进行相应,我们也无法关闭该窗口。为了解决这个问题,在例子二中我们把这个计数
的过程放到一个单独的线程中,而主线程则专门用来响应界面的操作,这时程序就可以正常运行。
(1)例子1
package hongqi.daiwei.lianyuan.java.multithread; import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Frame; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class Counter1 extends Applet { private int count = 0; private Button onOff = new Button("Toggle"); private Button start = new Button("Start"); private TextField t = new TextField(10); private boolean runFlag = true; public void init() { add(t); start.addActionListener(new StartL()); add(start); onOff.addActionListener(new OnOffL()); add(onOff); super.init(); } public void go(){ while(true){ try { Thread.currentThread(); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if(runFlag){ t.setText(Integer.toString(count++)); } } } class StartL implements ActionListener{ public void actionPerformed(ActionEvent e) { go(); } } class OnOffL implements ActionListener{ public void actionPerformed(ActionEvent e) { runFlag = !runFlag; } } public static void main(int argv, String argc[][]){ Counter1 applet = new Counter1(); Frame aFrame = new Frame("Counter1"); aFrame.add(applet, BorderLayout.CENTER); aFrame.setSize(300, 200); applet.init(); applet.start(); aFrame.setVisible(true); aFrame.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) { System.exit(0); } }); } }
(2)例子2
线程类:
package hongqi.daiwei.lianyuan.java.multithread; public class SeparateSubTask extends Thread { Counter2 c = null; private boolean flag = true; private int count = 0; public SeparateSubTask(Counter2 c){ this.c = c; this.start(); } public void invertFlag(){ flag = !flag; } public void run() { while(true){ try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if(flag){ c.t.setText(Integer.toString(count++)); } } } }
主类:
package hongqi.daiwei.lianyuan.java.multithread; import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Frame; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class Counter1 extends Applet { private int count = 0; private Button onOff = new Button("Toggle"); private Button start = new Button("Start"); private TextField t = new TextField(10); private boolean runFlag = true; public void init() { add(t); start.addActionListener(new StartL()); add(start); onOff.addActionListener(new OnOffL()); add(onOff); super.init(); } public void go(){ while(true){ try { Thread.currentThread(); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if(runFlag){ t.setText(Integer.toString(count++)); } } } class StartL implements ActionListener{ public void actionPerformed(ActionEvent e) { go(); } } class OnOffL implements ActionListener{ public void actionPerformed(ActionEvent e) { runFlag = !runFlag; } } public static void main(int argv, String argc[][]){ Counter1 applet = new Counter1(); Frame aFrame = new Frame("Counter1"); aFrame.add(applet, BorderLayout.CENTER); aFrame.setSize(300, 200); applet.init(); applet.start(); aFrame.setVisible(true); aFrame.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) { System.exit(0); } }); } }
标签:
原文地址:http://www.cnblogs.com/liujinyao/p/4687745.html