ITEEDU

Java Gossip: 实作 Runnable 界面

一个进程(Process)是一个包括有自身执行地址的程序,在一个多任务的操作系统中,可以分配CPU时间给每一个进程,CPU在片段时间中执行某个进程,然后下一个时间片段跳至另一个进程去执行,由于转换速度很快,这使得每个程序像是在同时进行处理一般。

一个执行绪是进程中的一个执行流程,一个进程中可以同时包括多个执行绪,也就是说一个程序中同时可能进行多个不同的子流程,这使得一个程序可以像是同时间 处理多个事务,例如一方面接受网络上的数据,另一方面同时计算数据并显示结果,一个多执行绪程序可以同时间处理多个子流程。

在Java中要实现执行绪功能,可以实作Runnable接口,Runnable接口中只定义一个run()方法,然后实例化一个 Thread对象时,传入一个实作Runnable接口的对象作为自变量,Thread对象会调用Runnable对象的run()方法,进而执行当中所定义的流程。

下面这个程序是个简单的Swing程序,您可以看到如何实作Runnable接口及如何启动执行绪:

ThreadDemo.java
package onlyfun.caterpillar;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.*;
public class ThreadDemo extends JFrame {
	public ThreadDemo() {
		// 配置按钮
		JButton btn = new JButton("Click me");
		// 按下按钮后绘制圆圈
		btn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Thread thread1 = new Thread(new Runnable() {
					public void run() {
						Graphics g = getGraphics();
						for(int i = 10; i < 300; i+=10) {
							try {
								Thread.sleep(500);
								g.drawOval(i, 100, 10, 10);
							}
							catch(InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
				});
				Thread thread2 = new Thread(new Runnable() {
					public void run() {
						Graphics g = getGraphics();
						for(int i = 10; i < 300; i+=10) {
							try {
								Thread.sleep(500);
								g.drawOval(i, 150, 15, 15);
							}
							catch(InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
				});
				thread1.start();
				thread2.start();
			}
		});
		getContentPane().add(btn, BorderLayout.NORTH);
		// 取消按下窗口关闭钮预设动作
		setDefaultCloseOperation(
		WindowConstants.EXIT_ON_CLOSE);
		setSize(320, 200);
		setVisible(true);
	}
	public static void main(String[] args) {
		new ThreadDemo();
	}
}

将程序编译并执行时,您可以看到一个窗口,按下上面的按钮,您会看到两个圆在「同时」绘制,虽说是同时,其实也只是错觉而已,其实是CPU往来两个流程之间不断的进行绘制圆的动作而已。

Thread类别也实作了Runnable接口,您也可以继承Thread类别并重新定义它的run()方法,好处是可以使用Thread上的一些继承下来的方法,例如yield(),然而继承了Thread就表示您不能让您的类别再继承其它的类别。