JAVA范例 十三)多线程编程(3)

      线程应用实例

  实例244 下雪的村庄

package Chapter17;

import java.applet.Applet;
import java.awt.*;
import java.util.Random;

public class SnowVillage extends Applet implements Runnable {

	Thread thread;// 声明主线程

	Image off, images[];// 声明图片对象和图片数组

	Random random;// 声明一个随机数对象

	int flag, sonwNum, wind, thread_1, size;// 声明一些int型变量

	int[] X, Y;// 声明两个int型数组,分别表示X和Y坐标点

	long time = 0;// 表示时间

	Dimension ds;// 声明一个Dimension对象

	MediaTracker mt;// 声明一个MediaTracker对象

	int getValue(String s1, int s2, int max, int min) {// 获取HTML标记中命名参数的值

		String s = getParameter(s1);
		if (s != null) {

			if ((s2 = Integer.parseInt(s)) > max)
				return max;
			else if (s2 < min)
				return min;
			else
				return s2;

		} else
			return s2;

	}

	public void init() {// Applet小程序初始化
		this.setSize(300, 200);
		random = new Random();
		ds = getSize();
		off = createImage(ds.width, ds.height);// 创建一个图象
		sonwNum = getValue("sonwNum", 100, 500, 0);// 获取雪片的个数
		size = getValue("size", 3, 10, 3);// 获取雪片的大小
		thread_1 = getValue("threadsleep", 80, 1000, 10);// 获取休眠的时间
		// 获取绘制雪片的XY坐标值
		X = new int[sonwNum];
		Y = new int[sonwNum];
		for (int i = 0; i < sonwNum; i++) {

			X[i] = random.nextInt() % (ds.width / 2) + ds.width / 2;
			Y[i] = random.nextInt() % (ds.height / 2) + ds.height / 2;

		}

		mt = new MediaTracker(this);
		images = new Image[1];
		images[0] = getImage(getDocumentBase(), "xue.jpg");
		mt.addImage(images[0], 0);
		try {

			mt.waitForID(0);

		} catch (InterruptedException _ex) {
			return;
		}
		flag = 0;

	}

	public void start() {// 启动小程序

		if (thread == null) {

			thread = new Thread(this);
			thread.start();// 启动线程

		}

	}

	public void stop() {// 停止运行小程序

		thread = null;

	}

	public void run() {// 运行线程

		while (thread != null) {

			try {

				Thread.sleep(thread_1);

			} catch (InterruptedException _ex) {
				return;
			}
			repaint();

		}

	}

	public void snow(Graphics g) {// 绘制雪片

		g.setColor(Color.white);
		for (int i = 0; i < sonwNum; i++) {

			g.fillOval(X[i], Y[i], size, size);
			X[i] += random.nextInt() % 2 + wind;
			Y[i] += (random.nextInt() % 6 + 5) / 5 + 1;
			if (X[i] >= ds.width)
				X[i] = 0;
			if (X[i] < 0)
				X[i] = ds.width - 1;
			if (Y[i] >= ds.height || Y[i] < 0) {

				X[i] = Math.abs(random.nextInt() % ds.width);
				Y[i] = 0;

			}

		}

		wind = random.nextInt() % 5 - 2;

	}

	public void paint(Graphics g) {// 绘制组件

		off.getGraphics().setColor(Color.black);
		off.getGraphics().fillRect(0, 0, ds.width, ds.height);
		off.getGraphics().drawImage(images[0], 0, 0, this);
		snow(off.getGraphics());
		g.drawImage(off, 0, 0, null);

	}

	public void update(Graphics g) {// 重新绘制组件

		paint(g);

	}

}

 

  实例245 小飞侠

package Chapter17.example;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;

public class SplitLine extends Applet implements Runnable {
	private Image moveleft__1, moveright_1, moveleft_2, moveright_2, temp;// 声明Image对象
	private Image image;//
	private Graphics graphics;
	private Thread thread = null;
	private MediaTracker img_tracker;
	private int height, width;
	public void init() {// 初始化Applet小程序
		// 创建Image对象
		moveright_1 = getImage(getDocumentBase(), "3.jpg");
		moveright_2 = getImage(getDocumentBase(), "4.jpg");
		moveleft__1 = getImage(getDocumentBase(), "1.jpg");
		moveleft_2 = getImage(getDocumentBase(), "2.jpg");
		// 创建MediaTracker对象
		img_tracker = new MediaTracker(this);
		// 将图片对象加载到媒体跟踪器中
		img_tracker.addImage(moveright_1, 0);
		img_tracker.addImage(moveleft__1, 0);
		img_tracker.addImage(moveright_2, 0);
		img_tracker.addImage(moveleft_2, 0);
		// 获取Applet的长和宽
		width = this.size().width;
		height = this.size().height;
		try {
			img_tracker.waitForID(0);// 跟踪指定ID的图象
		} catch (InterruptedException e) {
		}
		// 创建图象区
		image = createImage(width, height);
		// 创建Graphics对象
		graphics = image.getGraphics();
	}
	public void start() {// Applet小程序的start方法
		if (thread == null) {
			thread = new Thread(this);
			thread.start();// 开始运行线程
		}
	}
	public void run() {// 线程的run方法
		Color fg = this.getForeground();
		int imgWidth, imageHeight, x = 0, y = 0;
		boolean forward = true;
		imgWidth = moveright_1.getWidth(this);
		imageHeight = moveright_1.getHeight(this);
		y = (height - imageHeight) / 2;
		fg = Color.blue;// 设置分割线的颜色
		try {
			while (thread != null) {
				thread.sleep(200);
				if (forward) {
					x += 15;
					if ((x % 2) == 1) {
						temp = moveright_1;
					} else {
						temp = moveright_2;
					}
					if (x >= (width - imgWidth)) {
						forward = false;
					}
				} else {
					x -= 15;
					if ((x % 2) == 1) {
						temp = moveleft__1;
					} else {
						temp = moveleft_2;
					}
					if (x == 0) {
						forward = true;
					}
				}
				graphics.setColor(Color.white);// 设置小程序的背景颜色
				graphics.fillRect(0, 0, width, height);
				graphics.setColor(fg.brighter().darker());
				graphics.drawLine(0, (height - imageHeight) / 2 + imageHeight,
						width, (height - imageHeight) / 2 + imageHeight);
				graphics.setColor(fg.darker().brighter());
				graphics.drawLine(0, (height - imageHeight) / 2 + imageHeight,
						width, (height - imageHeight) / 2 + imageHeight);
				graphics.drawImage(temp, x, y, this);
				repaint();
			}
		} catch (InterruptedException e) {
		}
	}
	public void update(Graphics g) {
		paint(g);
	}
	public void paint(Graphics g) {
		g.drawImage(image, 0, 0, this);
	}
}

 

  实例246 飞流直下

package Chapter17.status;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;

public class Faucet extends Applet implements Runnable {
	final int Max = 1000;// 水滴的最大个数
	Drop d[];// 声明一个水滴对象
	int width, height, X, Y;// 声明Applet小程序的宽和高,及以XY坐标中心
	Image off;// 声明一个图片对象
	Graphics graphics;// 声明一个Graphics对象
	Thread thread;// 声明一个线程对象
	public void init() {// Applet小程序初始化
		this.setSize(300, 200);
		setBackground(Color.gray);
		width = getSize().width;
		height = getSize().height;
		d = new Drop[Max];
		for (int i = 0; i < Max; i++)
			d[i] = new Drop();
		off = createImage(width, height);
		graphics = off.getGraphics();
	}
	public void start() {// 开始执行小程序
		thread = new Thread(this);
		thread.start();
	}
	public void stop() {// 停止执行小程序
		thread = null;
	}
	public void update(Graphics g) {// 重新绘制小程序
		paint(g);
	}
	public void paint(Graphics g) {// 绘制组件
		g.drawImage(off, 0, 0, this);
	}
	public void run() {// 运行线程
		boolean reset = false;
		int i, t = 0;
		while (true) {
			graphics.clearRect(0, 0, width, height);
			graphics.setColor(Color.white);
			graphics.drawLine(0, 15, 10, 15);
			for (i = 0; i < Max; i++) {
				graphics.fillOval((int) d[i].X, (int) d[i].Y, 3, 3);
				d[i].X = d[i].X + d[i].newX;
				if (d[i].X > 10) {
					d[i].Y += d[i].newY * d[i].time / 1000;
					d[i].newY = (int) 9.8 * d[i].time;
					d[i].time++;
				}
				if (d[i].Y > height) {
					d[i].reset();
				}
			}
			repaint();
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
			}
		}
	}
}
class Drop {// 水滴类
	double X, Y;
	double newX, newY;
	int time;
	public Drop() {
		reset();
	}
	public void reset() {// 重新设置绘制水滴的位置和大小
		X = (int) (Math.random() * -40);
		Y = (int) (Math.random() * 5 + 10);
		newX = Math.random() * 3 + 1.0;
		newY = 0;
		time = 0;
	}
}

 

  实例247 多线程断点续传

package Chapter17.download;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;

//Java实现网络文件传输,在客户端请求Web服务器传输指定文件,并将文件保存。
public class ResumeUpload {
	private String downSource = "http://kent.dl.sourceforge.net/sourceforge/jamper/Sample.zip"; // 定义Web地址和文件名
	private String savePath = "d:\\temp"; // 定义存文件路径
	private String saveName = "汉仪YY字体.zip"; // 定义文件名
	public ResumeUpload() {
		try {
			FileInfo bean = new FileInfo(downSource, savePath, saveName, 5);
			FTPthread fileFetch = new FTPthread(bean);
			fileFetch.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		new ResumeUpload();
	}
}
class FTPthread extends Thread { // 传输文件线程类
	FileInfo siteInfoBean = null; // 文件信息Bean
	long[] nPos;
	long[] startPos; // 开始位置
	long[] endPos; // 结束位置
	FilePart[] fileSplitterFetch; // 子线程对象
	long nFileLength; // 文件长度
	boolean bFirst = true; // 是否第一次取文件
	boolean bStop = false; // 停止标志
	File tmpFile; // 文件传输临时信息
	DataOutputStream output; // 输出到文件的输出流
	public FTPthread(FileInfo bean) throws IOException {
		siteInfoBean = bean;
		tmpFile = new File(bean.getSFilePath() + File.separator
				+ bean.getSFileName() + ".info");
		if (tmpFile.exists()) {
			bFirst = false;
			readInform();
		} else {
			startPos = new long[bean.getNSplitter()];
			endPos = new long[bean.getNSplitter()];
		}
	}
	public void run() {
		// 获得文件长度
		// 分割文件
		// 实例PartCacth
		// 启动PartCacth线程
		// 等待子线程返回
		try {
			if (bFirst) {
				nFileLength = getFileSize();
				if (nFileLength == -1) {
					System.err.println("File Length is not known!");
				} else if (nFileLength == -2) {
					System.err.println("File is not access!");
				} else {
					for (int i = 0; i < startPos.length; i++) {
						startPos[i] = (long) (i * (nFileLength / startPos.length));
					}
					for (int i = 0; i < endPos.length - 1; i++) {
						endPos[i] = startPos[i + 1];
					}
					endPos[endPos.length - 1] = nFileLength;
				}
			}
			// 启动子线程
			fileSplitterFetch = new FilePart[startPos.length];
			for (int i = 0; i < startPos.length; i++) {
				fileSplitterFetch[i] = new FilePart(siteInfoBean.getSSiteURL(),
						siteInfoBean.getSFilePath() + File.separator
								+ siteInfoBean.getSFileName(), startPos[i],
						endPos[i], i);
				AddInform.log("Thread " + i + " , 开始位置 = " + startPos[i]
						+ ", 结束位置 = " + endPos[i]);
				fileSplitterFetch[i].start();
			}
			// 等待子线程结束
			// int count = 0;
			// 是否结束while循环
			boolean breakWhile = false;
			while (!bStop) {
				writeInform();
				AddInform.sleep(500);
				breakWhile = true;
				for (int i = 0; i < startPos.length; i++) {
					if (!fileSplitterFetch[i].bDownOver) {
						breakWhile = false;
						break;
					}
				}
				if (breakWhile)
					break;
			}
			System.out.println("文件传输结束!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	// 获得文件长度
	public long getFileSize() {
		int nFileLength = -1;
		try {
			URL url = new URL(siteInfoBean.getSSiteURL());
			HttpURLConnection httpConnection = (HttpURLConnection) url
					.openConnection();
			httpConnection.setRequestProperty("User-Agent", "NetFox");
			int responseCode = httpConnection.getResponseCode();
			if (responseCode >= 400) {
				processErrorCode(responseCode);
				return -2; // -2 为Web服务器响应错误
			}
			String sHeader;
			for (int i = 1;; i++) {
				sHeader = httpConnection.getHeaderFieldKey(i);
				if (sHeader != null) {
					if (sHeader.equals("Content-Length")) {
						nFileLength = Integer.parseInt(httpConnection
								.getHeaderField(sHeader));
						break;
					}
				} else
					break;
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		AddInform.log(nFileLength);
		return nFileLength;
	}
	// 保存传输信息(文件指针位置)
	private void writeInform() {
		try {
			output = new DataOutputStream(new FileOutputStream(tmpFile));
			output.writeInt(startPos.length);
			for (int i = 0; i < startPos.length; i++) {
				output.writeLong(fileSplitterFetch[i].startPos);
				output.writeLong(fileSplitterFetch[i].endPos);
			}
			output.close();
		} catch (Exception e) {
			System.out.println("保存传输信息失败");
		}
	}
	// 读取保存的下载信息(文件指针位置)
	private void readInform() {
		try {
			DataInputStream input = new DataInputStream(new FileInputStream(
					tmpFile));
			int nCount = input.readInt();
			startPos = new long[nCount];
			endPos = new long[nCount];
			for (int i = 0; i < startPos.length; i++) {
				startPos[i] = input.readLong();
				endPos[i] = input.readLong();
			}
			input.close();
			// 判断每块的文件开始位置是否大于结束位置
			for (int i = 0; i < startPos.length; i++) {
				if (startPos[i] > endPos[i]) {
					startPos[i] = endPos[i];
				}
			}
		} catch (Exception e) {
			System.out.println("读取保存的下载信息失败");
		}
	}
	private void processErrorCode(int nErrorCode) {
		System.err.println("Error Code : " + nErrorCode);
	}
	// 停止文件传输
	public void doStop() {
		bStop = true;
		for (int i = 0; i < startPos.length; i++)
			fileSplitterFetch[i].splitterStop();
	}
}
class FileInfo { // 定义获取和设置相关文件信息类
	private String sSiteURL; // 定义URL变量
	private String sFilePath; // 定义存文件路径变量
	private String sFileName; // 定义文件名变量
	private int nSplitter; // 定义传输文件计数值
	public FileInfo() {
		this("", "", "", 5); // 设置传输文件计数值
	}
	public FileInfo(String sURL, String sPath, String sName, int nSpiltter) {
		sSiteURL = sURL;
		sFilePath = sPath;
		sFileName = sName;
		this.nSplitter = nSpiltter;
	}
	public String getSSiteURL() {
		return sSiteURL;
	}
	public void setSSiteURL(String value) {
		sSiteURL = value;
	}
	public String getSFilePath() {
		return sFilePath;
	}
	public void setSFilePath(String value) {
		sFilePath = value;
	}
	public String getSFileName() {
		return sFileName;
	}
	public void setSFileName(String value) {
		sFileName = value;
	}
	public int getNSplitter() {
		return nSplitter;
	}
	public void setNSplitter(int nCount) {
		nSplitter = nCount;
	}
}
class FilePart extends Thread {
	String sURL; // 定义文件传输时使用的变量
	long startPos; // 分段文件传输开始位置
	long endPos; // 分段文件传输结束位置
	int nThreadID; // 子线程ID
	boolean bDownOver = false; // 完成文件传输
	boolean bStop = false; // 停止文件传输
	SaveFile fileAccess = null;
	public FilePart(String sURL, String sName, long nStart, long nEnd, int id)
			throws IOException {
		this.sURL = sURL;
		this.startPos = nStart;
		this.endPos = nEnd;
		nThreadID = id;
		fileAccess = new SaveFile(sName, startPos);
	}
	public void run() {
		while (startPos < endPos && !bStop) {
			try {
				URL url = new URL(sURL);
				HttpURLConnection httpConnection = (HttpURLConnection) url
						.openConnection();
				httpConnection.setRequestProperty("User-Agent", "NetFox");
				String sProperty = "bytes=" + startPos + "-";
				httpConnection.setRequestProperty("RANGE", sProperty);
				AddInform.log(sProperty);
				InputStream input = httpConnection.getInputStream();
				byte[] b = new byte[1024];
				int nRead;
				while ((nRead = input.read(b, 0, 1024)) > 0
						&& startPos < endPos && !bStop) {
					startPos += fileAccess.write(b, 0, nRead);
				}
				AddInform.log("Thread " + nThreadID + " is over!");
				bDownOver = true;
			} catch (Exception e) {
				System.out.println(getName() + " 线程运行异常");
			}
		}
		bDownOver = true;
	}
	public void logResponseHead(HttpURLConnection con) {
		for (int i = 1;; i++) {
			String header = con.getHeaderFieldKey(i);
			if (header != null)
				AddInform.log(header + " : " + con.getHeaderField(header));
			else
				break;
		}
	}
	public void splitterStop() {
		bStop = true;
	}
}
class SaveFile implements Serializable { // 定义访问文件类
	RandomAccessFile oSavedFile;
	long nPos;
	public SaveFile() throws IOException {
		this("", 0);
	}
	public SaveFile(String sName, long nPos) throws IOException {
		oSavedFile = new RandomAccessFile(sName, "rw");
		this.nPos = nPos;
		oSavedFile.seek(nPos);
	}
	public synchronized int write(byte[] b, int nStart, int nLen) {
		int n = -1;
		try {
			oSavedFile.write(b, nStart, nLen);
			n = nLen;
		} catch (IOException e) {
			System.out.println("同步存储信息异常");
		}
		return n;
	}
}
 class AddInform { // 定义输出提示信息及线程sleep类
	public AddInform() {
	}
	public static void sleep(int nSecond) {
		try {
			Thread.sleep(nSecond);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void log(String sMsg) {
		System.out.println(sMsg);
	}
	public static void log(int sMsg) {
		System.out.println(sMsg);
	}
}

 

  实例248 滚动的珠子

package Chapter17;

import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MoveBall extends Frame implements ActionListener {
	// 创建3个按扭组件,分别代表开始、停止和退出
	private Button quit = new Button("退出");
	private Button start = new Button("开始");
	private Button stop = new Button("停止");
	private DrawBall balls[] = new DrawBall[20];
	// 构造方法,对各组件进行初始化
	public MoveBall() {
		super();
		setLayout(new FlowLayout());
		add(quit);
		quit.addActionListener(this);
		add(start);
		start.addActionListener(this);
		add(stop);
		stop.addActionListener(this);
		validate();
		this.setBackground(Color.black);
		this.setSize(300, 300);
		this.setVisible(true);
		for (int i = 0; i < balls.length; i++) {
			int x = (int) (getSize().width * Math.random());
			int y = (int) (getSize().height * Math.random());
			balls[i] = new DrawBall(this, x, y);
		}
	}
	public void actionPerformed(ActionEvent e) {// 为Button添加事件处理
		if (e.getSource() == stop) {// 单击停止按扭
			for (int i = 0; i < balls.length; i++) {
				balls[i].setRun();
			}
		}
		if (e.getSource() == start) {// 单击开始按扭
			for (int i = 0; i < balls.length; i++) {
				balls[i].setRun();
				balls[i] = new DrawBall(this, balls[i].x, balls[i].y);
			}
		}
		if (e.getSource() == quit) {// 单击退出按扭
			System.exit(0);
		}
	}
	public void paint(Graphics g) {// 绘制组件
		for (int i = 0; i < balls.length; i++)
			if (balls[i] != null)
				balls[i].paintBall(g);
	}
	public static void main(String[] args) {// 程序的入口处
		MoveBall t = new MoveBall();
	}
}
class DrawBall extends Thread {// 绘画珠子
	// 利用随机数获取绘制珠子的位置
	private int a = 2 * (1 - 2 * (int) Math.round(Math.random()));
	private int b = 2 * (1 - 2 * (int) Math.round(Math.random()));
	private boolean running = false;// 控制是否绘制珠子的标志
	private MoveBall table = null;// 声明一个MoveBall对象
	protected int x, y;// 定义XY坐标点
	public DrawBall(MoveBall _table, int _x, int _y) {// 构造方法,给其成员变量赋初值
		table = _table;
		x = _x;
		y = _y;
		start();
	}
	public void start() {
		running = true;
		super.start();// 启动线程
	}
	public void setRun() {
		running = false;
	}
	public void run() {// 重写Thread类的run方法
		while (running) {
			move();
			try {
				sleep(50);
			} catch (InterruptedException e) {
				System.out.println(e.getMessage());
			}
			table.repaint();
		}
	}
	public void paintBall(Graphics g) {// 自定义绘制珠子的方法
		g.setColor(Color.red);
		g.fillOval(x, y, 20, 20);
	}
	private void move() {// 珠子在滚动
		x += a;
		y += b;
		if ((x > table.getSize().width) || (x < 0)) {
			a *= (-1);
		}
		if ((y > table.getSize().height) || (y < 0)) {
			b *= (-1);
		}
	}
}

 

  实例249 余额查询

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class QueryBalance extends JPanel {
	private JTextField acctext;// 声明一个录入帐号的输入框
	private JTextField pass;// 声明一个录入帐号密码的输入框
	private JButton button1;// 声明一个查询按扭
	private JButton button2;// 声明一个取消按扭
	private JLabel balanceL;// 声明一个录入帐号的输入框
	private volatile Thread lookupThread;// 创建一个线程
	public QueryBalance() {// 构造方法
		mainFrame();
		searchEvents();
	}
	private void mainFrame() {
		// 创建组件
		JLabel Lacct = new JLabel("账户编号:");
		JLabel Lpass = new JLabel("密码:");
		acctext = new JTextField(12);
		pass = new JTextField(4);
		JPanel mainPanel = new JPanel();// 创建一个面板对象
		mainPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		// 将组件添加到面板中
		mainPanel.add(Lacct);
		mainPanel.add(acctext);
		mainPanel.add(Lpass);
		mainPanel.add(pass);
		// 创建Button按扭
		button1 = new JButton("查询");
		button2 = new JButton("取消查询");
		button2.setEnabled(false);
		// 创建装载Button组件的面板
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new GridLayout(1, -1, 5, 5));
		// 将Button组件添加到buttonPanel面板中
		buttonPanel.add(button1);
		buttonPanel.add(button2);
		JPanel addPanel = new JPanel();
		addPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		addPanel.add(buttonPanel);// 将buttonPanel面板添加到addPanel面板中
		JLabel balancePrefixL = new JLabel("账户余额:");
		balanceL = new JLabel("查询未知");
		// 将用于显示查询结果的组件放到searchPanel面板中
		JPanel searchPanel = new JPanel();
		searchPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
		searchPanel.add(balancePrefixL);
		searchPanel.add(balanceL);
		JPanel showPanel = new JPanel();
		showPanel.setLayout(new GridLayout(-1, 1, 5, 5));
		showPanel.add(mainPanel);
		showPanel.add(addPanel);
		showPanel.add(searchPanel);
		setLayout(new BorderLayout());
		add(showPanel, BorderLayout.NORTH);
	}
	private void searchEvents() {// 为查询按扭和取消按扭
		button1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				searchING();
			}
		});
		button2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cancelSearch();
			}
		});
	}
	private void searchING() {// 正在查询的过程中
		ensureEventThread();
		button1.setEnabled(false);
		button2.setEnabled(true);
		balanceL.setText("正在查询 请稍候 ...");
		// 获取录入的账号和密码
		String acct = acctext.getText();
		String pin = pass.getText();
		lookupMessage(acct, pin);
	}
	private void lookupMessage(String acct, String pin) {// 设置查询信息
		final String acctNum = acct;
		final String pinNum = pin;
		Runnable lookupRun = new Runnable() {
			public void run() {
				String bal = searchAndCheck(acctNum, pinNum);
				setSafe(bal);
			}
		};
		lookupThread = new Thread(lookupRun, "lookupThread");
		lookupThread.start();
	}
	private String searchAndCheck(String acct, String pin) {// 检查账号和密码是否输入正确
		try {
			Thread.sleep(5000);
			if (!acct.equals("220302113325") && pin.equals("198713")) {
				return "您输入的账号错误!";
			} else if (acct.equals("220302113325") && !pin.equals("198713")) {
				return "您输入的密码错误!";
			}
			return "1,234.56";
		} catch (InterruptedException x) {
			return "取消查询";
		}
	}
	private void setSafe(String newBal) {// 进行安全设置
		final String newBalance = newBal;
		Runnable r = new Runnable() {
			public void run() {
				try {
					setValue(newBalance);
				} catch (Exception x) {
					x.printStackTrace();
				}
			}
		};
		SwingUtilities.invokeLater(r);
	}
	private void setValue(String newBalance) {// 获取查询结果
		ensureEventThread();
		balanceL.setText(newBalance);
		button2.setEnabled(false);// 正在查询的过程中,取消查询按扭是不用的
		button1.setEnabled(true);
	}
	private void cancelSearch() {// 取消查询
		ensureEventThread();
		button2.setEnabled(false); // prevent additional requests
		if (lookupThread != null) {
			lookupThread.interrupt();
		}
	}
	private void ensureEventThread() {
		if (SwingUtilities.isEventDispatchThread()) {
			return;
		}
		throw new RuntimeException("只有线程可以调用此方法");
	}
	public static void main(String[] args) {
		QueryBalance qb = new QueryBalance();
		JFrame f = new JFrame("Balance Lookup");
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		f.setContentPane(qb);
		f.setSize(400, 150);
		f.setVisible(true);
	}
}

 

  实例250 滚动的文字

package Chapter17.status;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class CryptoService extends JComponent {
	private BufferedImage image;// 声明一个BufferedImage类对象
	private Dimension imageOfSize;// 声明一个Dimension类对象
	private volatile int currOffset;// 声明一个用于表示偏移量的变量
	private Thread thread;// 声明一个线程
	private volatile boolean flag;
	public CryptoService(String text) {
		currOffset = 0;
		buildImage(text);
		setMinimumSize(imageOfSize);
		setPreferredSize(imageOfSize);
		setMaximumSize(imageOfSize);
		setSize(imageOfSize);
		flag = true;
		Runnable r = new Runnable() {
			public void run() {
				try {
					ScrollING();
				} catch (Exception x) {
					x.printStackTrace();
				}
			}
		};
		thread = new Thread(r, "ScrollText");
		thread.start();
	}
	private void buildImage(String text) {
		RenderingHints renderHints = new RenderingHints(
				RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);// 根据抗锯齿提示键和抗锯齿提示值来创建一个RenderingHints类对象
		renderHints.put(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);// 将指定的呈现提示键映射到此RenderingHints对象中的指定呈现指示值。
		BufferedImage scratchImage = new BufferedImage(1, 1,
				BufferedImage.TYPE_INT_RGB);// 构造一个类型为预定义的图像
		Graphics2D scratchG2 = scratchImage.createGraphics();// 创建一个Graphics2D类对象
		scratchG2.setRenderingHints(renderHints);// 设置呈现算法
		Font font = new Font("Serif", Font.BOLD | Font.ITALIC, 24);// 创建一个Font字体对象
		FontRenderContext frc = scratchG2.getFontRenderContext();// 创建一个FontRenderContext对象
		TextLayout tl = new TextLayout(text, font, frc);// 创建一个TextLayout对象
		Rectangle2D textBounds = tl.getBounds();// 创建一个Rectangle2D对象
		int textWidth = (int) Math.ceil(textBounds.getWidth());// 设置文字的显示宽度
		int textHeight = (int) Math.ceil(textBounds.getHeight());// 设置文字的显示长度
		int horizontalPad = 10;// 设置水平间距为10象素
		int verticalPad = 6;// 设置垂直间距为6象素
		imageOfSize = new Dimension(// 创建Dimension对象
				textWidth + horizontalPad, textHeight + verticalPad);
		image = new BufferedImage(
				// 创建BufferedImage对象
				imageOfSize.width, imageOfSize.height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = image.createGraphics();
		g2.setRenderingHints(renderHints);
		int baselineOffset = (verticalPad / 2) - ((int) textBounds.getY());// 基线的偏移量
		g2.setColor(Color.black);// 设为黑色背影
		g2.fillRect(0, 0, imageOfSize.width, imageOfSize.height);
		g2.setColor(Color.WHITE);// 白色字体
		tl.draw(g2, 0, baselineOffset);
		scratchG2.dispose();
		scratchImage.flush();
		g2.dispose();
	}
	public void paint(Graphics g) {
		// 将当前的剪贴区设置为由给定坐标指定的矩形。
		g.setClip(0, 0, imageOfSize.width, imageOfSize.height);
		int localOffset = currOffset; // 本地偏移量是不断的变化的
		g.drawImage(image, -localOffset, 0, this);
		g.drawImage(image, imageOfSize.width - localOffset, 0, this);
		// 绘画出边框
		g.setColor(Color.red);
		g.drawRect(0, 0, imageOfSize.width - 1, imageOfSize.height - 1);
	}
	private void ScrollING() {// 执行滚动操作
		while (flag) {
			try {
				Thread.sleep(100); 
				currOffset = (currOffset + 1) % imageOfSize.width;
				repaint();
			} catch (InterruptedException x) {
				Thread.currentThread().interrupt();
			}
		}
	}
	public static void main(String[] args) {
		CryptoService st = new CryptoService("教师节快乐");
		JPanel p = new JPanel(new FlowLayout());
		p.add(st);
		JFrame f = new JFrame("滚动的文字");
		f.setContentPane(p);
		f.setSize(400, 100);
		f.setVisible(true);
	}
}

 

  实例251 漂浮效果

package Chapter17;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import Chapter17.status.CryptoService;

public class FloatingEffect extends Object {
	private Component comp;// 创建一个Component对象
	// 定义显示位置的X、Y坐标点
	private int initX;
	private int initY;
	// 定义偏移位置的X、Y坐标点
	private int offsetX;
	private int offsetY;
	// 标志是否是第一次执行
	private boolean firstTime;
	// 声明一个实现Runnable接口的匿名内部类对象
	private Runnable runable;
	// 声明一个线程对象
	private Thread thread;
	// 标识是否停止浮动
	private volatile boolean flag;
	// 构造方法,为其成员变量初始化
	public FloatingEffect(Component comp, int initX, int initY, int offsetX,
			int offsetY) {
		this.comp = comp;
		this.initX = initX;
		this.initY = initY;
		this.offsetX = offsetX;
		this.offsetY = offsetY;
		firstTime = true;
		runable = new Runnable() {
			public void run() {
				newPosition();
			}
		};
		flag = true;
		Runnable r = new Runnable() {// 实现Runnable接口的匿名内部类
			public void run() {
				try {
					floatING();
				} catch (Exception x) {
					// in case ANY exception slips through
					x.printStackTrace();
				}
			}
		};
		thread = new Thread(r);// 线程实例化
		thread.start();// 启动线程
	}
	private void floatING() {// 执行漂浮
		while (flag) {
			try {
				Thread.sleep(200);
				SwingUtilities.invokeAndWait(runable);
			} catch (InterruptedException ix) {
				// ignore
			} catch (Exception x) {
				x.printStackTrace();
			}
		}
	}
	private void newPosition() {// 更新新的坐标值
		if (!comp.isVisible()) {// 判断此组件在其父容器内是否可见
			return;
		}
		Component parent = comp.getParent();// 获得此组件的父级
		if (parent == null) {
			return;
		}
		Dimension parentSize = parent.getSize();
		if ((parentSize == null) && (parentSize.width < 1)
				&& (parentSize.height < 1)) {
			return;
		}
		int newX = 0;
		int newY = 0;
		if (firstTime) {
			firstTime = false;
			newX = initX;
			newY = initY;
		} else {
			Point loc = comp.getLocation();
			newX = loc.x + offsetX;
			newY = loc.y + offsetY;
		}
		newX = newX % parentSize.width;
		newY = newY % parentSize.height;
		if (newX < 0) {
			// 绕到另一侧
			newX += parentSize.width;
		}
		if (newY < 0) {
			newY += parentSize.height;
		}
		comp.setLocation(newX, newY);
		parent.repaint();
	}
	public static void main(String[] args) {// 执行该程序的主入中
		Component[] comp = new Component[6];// 创建一个Component组件数组
		comp[0] = new CryptoService("幸福");
		comp[1] = new CryptoService("快乐");
		comp[2] = new ImageShow("E:\\tupian\\1.jpg", 30);
		comp[3] = new ImageShow("E:\\tupian\\1.jpg", 30);
		comp[4] = new ImageShow("E:\\tupian\\2.jpg", 100);
		comp[5] = new ImageShow("E:\\tupian\\2.jpg", 100);
		JPanel p = new JPanel();
		p.setBackground(Color.white);
		p.setLayout(null);
		for (int i = 0; i < comp.length; i++) {
			p.add(comp[i]);
			int x = (int) (300 * Math.random());
			int y = (int) (200 * Math.random());
			int xOff = 2 - (int) (5 * Math.random());
			int yOff = 2 - (int) (5 * Math.random());
			new FloatingEffect(comp[i], x, y, xOff, yOff);
		}
		JFrame f = new JFrame("漂浮效果");
		f.setContentPane(p);
		f.setSize(400, 300);
		f.setVisible(true);
	}
}
class ImageShow extends JComponent {// 其类的主
	private Dimension size;// 显示图像的尺寸
	private volatile int imgLength;// 绘制图像的大小
	private Thread thread;// 声明一个线程对象
	private Image im;// 声明一个图像对象
	private static String imgUrl = "";// 表示图片所示磁盘的位置
	public ImageShow(String image, int n) {
		imgUrl = image;
		imgLength = 0;
		size = new Dimension(n, n);
		creatImage();
		setMinimumSize(size);// 设置此组件的最小尺寸
		setPreferredSize(size);// 设置此组件的首先尺寸
		setMaximumSize(size);// 设置此组件的最大尺寸
		setSize(size);// 调整组件的大小
		Runnable r = new Runnable() {
			public void run() {
				try {
					showING();
				} catch (Exception x) {
					x.printStackTrace();
				}
			}
		};
		thread = new Thread(r, "ImageShow");
		thread.start();
	}
	private void creatImage() {// 获取图片对象
		ImageIcon ic = new ImageIcon(imgUrl);
		im = ic.getImage();
	}
	public void paint(Graphics g) {// 绘制图像
		g.drawImage(im, imgLength, imgLength + 2, this);
	}
	private void showING() {// 显示图象
		while (true) {
			try {
				Thread.sleep(300); // 休眠3毫秒
				imgLength = imgLength + 1;
				if (imgLength > 30) {// 如果图象边框的长度大于30
					imgLength = 0;// 边框设为0
				}
				repaint();// 重新绘制图像
			} catch (InterruptedException x) {
				Thread.currentThread().interrupt();
			}
		}
	}
}

 

  实例252 监视内存的使用情况

package Chapter17;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;

//监控内存
public class Memory extends JFrame {
	private JPanel panel;
	private BorderLayout layout = new BorderLayout();
	// 创建JProgressBar对象并实例化
	private JProgressBar bar_1 = new JProgressBar();
	private JLabel label_1 = new JLabel();
	private JLabel label_2 = new JLabel();
	private void Initial() throws Exception {
		panel = (JPanel) this.getContentPane();
		panel.setLayout(layout);
		this.setSize(new Dimension(305, 215));
		this.setTitle("内存的使用情况");
		label_1.setFont(new java.awt.Font("Dialog", 0, 14));
		label_1.setHorizontalAlignment(SwingConstants.CENTER);
		label_1.setText("自定义任务管理器");
		bar_1.setOrientation(JProgressBar.VERTICAL);
		bar_1.setFont(new java.awt.Font("Dialog", 0, 14));
		bar_1.setToolTipText("");
		bar_1.setStringPainted(true);
		label_2.setFont(new java.awt.Font("Dialog", 0, 14));
		label_2.setText("");
		panel.add(bar_1, BorderLayout.CENTER);
		panel.add(label_1, BorderLayout.NORTH);
		panel.add(label_2, BorderLayout.SOUTH);
		ProgressThread pt = new ProgressThread(this.bar_1, this.label_2);
		pt.start();
		this.setVisible(true);
	}
	public static void main(String[] args) {
		try {
			new Memory().Initial();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
class ProgressThread extends Thread {
	JProgressBar jpb;
	JLabel jl;
	public ProgressThread(JProgressBar jpb, JLabel jl) {
		this.jpb = jpb;
		this.jl = jl;
	}
	public void run() {
		int min = 0;
		int max = 100;
		int free = 0;
		int totle = 0;
		int status = 0;
		jpb.setMinimum(min);
		jpb.setMaximum(max);
		jpb.setValue(status);
		while (true) {
			totle = (int) (Runtime.getRuntime().totalMemory() / 1024);
			free = (int) (Runtime.getRuntime().freeMemory() / 1024);
			jl.setText("可用内存"
					+ (int) (Runtime.getRuntime().freeMemory() / 1024) + "K"
					+ " 总共分配的内存:"
					+ (int) (Runtime.getRuntime().totalMemory() / 1024) + "K");
			status = (int) (free * 100 / totle);
			jpb.setValue(status);
			jpb.setString("可用内存:" + status + "%");
			try {
				this.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

 

  实例253 璀璨的星空

package Chapter17.example;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;

public class Universe extends java.applet.Applet implements Runnable {
	int Width, Height;// 定义小程序的长和宽
	Thread thread = null;// 声明一个线程对象
	boolean suspend = false;// 是否暂停
	Image im;// 声明一个图象对象
	Graphics graphics;// 声明一个Graphics对象
	double rot, dx, ddx;// 声明double型变量
	int speed, stars, type;// 声明int型变量
	double defddx, max;// 声明double型变量
	Star pol[]; // 星光
	public void init() {// 初始化Applet小程序
		rot = 0;
		dx = 0;
		ddx = 0;
		Width = 300;
		Height = 300;
		String theSpeed = "25";
		Show("speed", theSpeed);
		speed = (theSpeed == null) ? 50 : Integer.valueOf(theSpeed).intValue();
		String theStars = "250";
		Show("stars", theStars);
		stars = (theStars == null) ? 30 : Integer.valueOf(theStars).intValue();
		try {
			im = createImage(Width, Height);
			graphics = im.getGraphics();
		} catch (Exception e) {
			graphics = null;
		}
		pol = new Star[stars];
		for (int i = 0; i < stars; i++)
			pol[i] = new Star(Width, Height, 150, type);
		System.out.println(Width + "," + Height);
	}
	public void paint(Graphics g) {// 绘制组件
		if (graphics != null) {
			paintStart(graphics);
			g.drawImage(im, 0, 0, this);
		} else {
			paintStart(g);
		}
	}
	public void paintStart(Graphics g) {
		g.setColor(Color.black);
		g.fillRect(0, 0, Width, Height);
		for (int i = 0; i < stars; i++)
			pol[i].DrawSelf(g, rot);
	}
	public void start() {// 启动Applet小程序
		if (thread == null) {
			thread = new Thread(this);
			thread.start();// 启动线程
		}
	}
	public void stop() {// 停止运行Applet小程序
		if (thread != null) {
			thread.stop();
			thread = null;
		}
	}
	public void run() {// 运行线程
		while (thread != null) {
			rot += dx;
			dx += ddx;
			if (dx > max)
				ddx = -defddx;
			if (dx < -max)
				ddx = defddx;
			try {
				Thread.sleep(speed);
			} catch (InterruptedException e) {
			}
			repaint();
		}
	}
	public void update(Graphics g) {// 重新绘制组伯
		paint(g);
	}
	public void Show(String theString, String theValue) {
		if (theValue == null) {
			System.out.println(theString + " : null");
		} else {
			System.out.println(theString + " : " + theValue);
		}
	}
}
class Star {// 代表星星类
	int H, V;
	int x, y, z;
	int type;
	Star(int width, int height, int depth, int type) {// 构造函数为各变量初始化
		this.type = type;
		H = width / 2;
		V = height / 2;
		x = (int) (Math.random() * width) - H;
		y = (int) (Math.random() * height) - V;
		if ((x == 0) && (y == 0))
			x = 10;
		z = (int) (Math.random() * depth);
	}
	public void DrawSelf(Graphics g, double rot) {// 根据坐标绘制星星
		double X, Y;
		int h, v, hh, vv;
		int d;
		z -= 2;
		if (z < -63)
			z = 100;
		hh = (x * 64) / (64 + z);
		vv = (y * 64) / (64 + z);
		X = (hh * Math.cos(rot)) - (vv * Math.sin(rot));
		Y = (hh * Math.sin(rot)) + (vv * Math.cos(rot));
		h = (int) X + H;
		v = (int) Y + V;
		if ((h < 0) || (h > (2 * H)))
			z = 100;
		if ((v < 0) || (v > (2 * H)))
			z = 100;
		setColor(g);
		if (type == 0) {
			d = (100 - z) / 50;
			if (d == 0)
				d = 1;
			g.fillRect(h, v, d, d);
		} else {
			d = (100 - z) / 20;
			g.drawLine(h - d, v, h + d, v);
			g.drawLine(h, v - d, h, v + d);
			if (z < 50) {
				d /= 2;
				g.drawLine(h - d, v - d, h + d, v + d);
				g.drawLine(h + d, v - d, h - d, v + d);
			}
		}
	}
	public void setColor(Graphics g) {// 给绘制的对象设置颜色
		if (z > 50) {
			g.setColor(Color.gray);
		} else if (z > 25) {
			g.setColor(Color.lightGray);
		} else {
			g.setColor(Color.white);
		}
	}
}

 

  实例254 银行和超市业务的模拟

package Chapter17.bank;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class SimulationSite extends Frame implements ActionListener {//模拟现场场景
	//定义全局成员常量
	protected static final int num_agents=10;
	protected static final int num_initial_agents=6;
	protected static final int max_customer_delay=9000;
	protected static final int max_teller_break=1000;
	protected static final int max_no_customers=2000;
	//创建Button组件
	private Button open = new Button("开门");
	private Button close = new Button("关门");
	private Button add = new Button("欢迎光临");
	private Button del = new Button("请慢走");
	private Bank bank = new Bank();
	private Finance supermarket = new Finance("");
	//添加窗口关闭事件
	private class WindowCloser extends WindowAdapter{
		public void windowClosing(WindowEvent e){
			bank.stop();
			supermarket.stop();
			System.exit(0);
		}
	}
	public SimulationSite(){//构造方法,进行组件初始化和布局
		super("SimulationSite");
		Panel buttons = new Panel();
		buttons.setLayout(new FlowLayout());
		buttons.add(open);
		open.addActionListener(this);
		buttons.add(close);
		close.addActionListener(this);
		buttons.add(add);
		add.addActionListener(this);
		buttons.add(del);
		del.addActionListener(this);
		this.addWindowListener(new WindowCloser());
		this.setLayout(new BorderLayout());
		add("West",bank);
		add("East",supermarket);
		add("South",buttons);
		validate();
		pack();
		show();
		bank.start();
		supermarket.start();
	}
	public void actionPerformed(ActionEvent e) {//为单击按扭做事件监听
		// TODO Auto-generated method stub
		if(e.getSource()==open){
			bank.openDoor();
			supermarket.openDoor();
		}else if(e.getSource()==close){
			bank.closeDoor();
			supermarket.closeDoor();
		}else if(e.getSource()==add){
			bank.addAgent();
			supermarket.addAgent();
		}else if(e.getSource()==del){
			bank.retireAgent();
			supermarket.retireAgent();
		}
	}
	public static void main(String[] args){//本程序的入口处
		SimulationSite sl = new SimulationSite();
	}
}
 class Finance extends Panel implements Runnable {
	protected Penson[] person = new Penson[SimulationSite.num_agents];
	protected Label[] labelAgent = new Label[SimulationSite.num_agents];
	protected Label labelQueue = new Label("已服务的顾客数:0");
	protected Label labelServed = new Label("Customers servers:0");
	protected Label labelWait = new Label("Customers wait:0");
	protected int numAgents = SimulationSite.num_initial_agents;
	protected int numCustomer = 0;// 顾客数
	protected long totalWait = 0L;// 等待顾客数
	private Thread thread = null;
	private boolean doorIsOpen = false;
	public Finance(String title) {
		super();
		setup(title);
	}
	public  void updateDisplay() {
	}
	public  void generateCustomer() {
	}
	public  Customer requestCustomerFor(int id) {
		return null;
	}
	public void checkoutCustomer(int handled, long waitTime) {// 更新顾客的数量,和正在等待的总人数
		numCustomer++;
		totalWait += waitTime;
	}
	public void addAgent() {// 增加人员
		if (numAgents < SimulationSite.num_agents) {
			person[numAgents] = new Penson(this, numAgents);
			person[numAgents].start();
			numAgents++;
		}
	}
	public void retireAgent() {// 减少人员
		if (numAgents > 1) {
			person[numAgents - 1].setRunING();
			numAgents--;
		}
	}
	public void start() {
		if (thread == null) {
			thread = new Thread(this);
			doorIsOpen = true;
			thread.start();// 启动当前线程
			for (int i = 0; i < numAgents; i++) {
				person[i].start();// 启动Person类中的线程
			}
		}
	}
	public void stop() {
		doorIsOpen = false;
		thread = null;
		for (int i = 0; i < numAgents; i++) {
			person[i].setRunING();
		}
	}
	public void openDoor() {// 营业
		doorIsOpen = true;
	}
	public void closeDoor() {// 打烊
		doorIsOpen = false;
	}
	public void run() {// 重写Runnable的run方法
		while (thread == Thread.currentThread()) {
			try {
				thread.sleep((int) Math.random()
						* SimulationSite.max_no_customers);
				if (doorIsOpen) {
					generateCustomer();
					updateDisplay();
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	private void setup(String title) {// 设置状态
		Panel agentPanel = new Panel();
		agentPanel.setLayout(new GridLayout(SimulationSite.num_agents + 3, 1));
		for (int i = 0; i < SimulationSite.num_agents; i++) {
			labelAgent[i] = new Label("Penson" + i + ":served 0");
			agentPanel.add(labelAgent[i]);
			person[i] = new Penson(this, i);
		}
		for (int i = numAgents; i < SimulationSite.num_agents; i++) {
			labelAgent[i].setText("Penson" + i + ":inactive");
		}
		agentPanel.add(labelQueue);
		agentPanel.add(labelServed);
		agentPanel.add(labelWait);
		setLayout(new BorderLayout());
		add("Center", agentPanel);
		add("North", new Label(title));
	}
}
class Penson extends Thread {// 创建一个Thread类的子类Penson类
	private boolean running = false;// 是否停止运行的标志
	private Finance bn = null;
	private int id = -1;// 客户id
	private int numCustomers = 0;// 顾客数量
	public Penson(Finance _bn, int _id) {
		this.bn = _bn;
		this.id = _id;
	}
	public void start() {
		running = true;
		super.start();// 启动线程
	}
	public void setRunING() {// 设置执行状态
		running = false;
	}
	public int getNum() {// 获取顾客数量
		return numCustomers;
	}
	private void releaseCustomer(Customer customer) {// 释放顾客对象
		numCustomers++;
		bn.checkoutCustomer(numCustomers, customer.getWaitTime(new Date()));
	}
	public void run() {// 重写Thread的run方法
		while (running) {
			try {
				sleep((int) (Math.random() * SimulationSite.max_teller_break) + 1000);// 随面休眠
				Customer customer = bn.requestCustomerFor(id);
				if (customer != null) {
					sleep(customer.getDelayTime());
					releaseCustomer(customer);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
class Bank extends Finance implements Runnable {
	private ObjectQueue queue = null;
	public Bank() {
		super("中国北京银行");// 调用父类的带参构造方法
		queue = new ObjectQueue();// 创建ObjectQueue对象
	}
	public void updateDisplay() {// 更新显示
		labelServed.setText("已服务的顾客数:" + numCustomer);// 设置标签的显示内容
		if (numCustomer != 0) {
			labelWait.setText("平均等待:" + (totalWait / numCustomer));
			for (int i = 0; i < numAgents; i++) {
				labelAgent[i].setText("顾客:" + i + ": 已服务" + person[i].getNum());
			}
			for (int i = numAgents; i < SimulationSite.num_agents; i++) {
				labelAgent[i].setText("顾客:" + i + ": 未服务");
				labelQueue.setText("正在等待的顾客数:" + queue.getSize());
			}
		}
	}
	public void generateCustomer() {// 增加新的顾客,表示又有新的顾客光临
		queue.insert(new Customer());
	}
	public Customer requestCustomerFor(int id) {// 表示有顾客发出想进行服务的需求
		return queue.requestCustomer();
	}
}
//class SimulationSite extends Frame implements ActionListener {// 模拟现场场景
//	// 定义全局成员常量
//	protected static final int num_agents = 10;
//	protected static final int num_initial_agents = 6;
//	protected static final int max_customer_delay = 9000;
//	protected static final int max_teller_break = 1000;
//	protected static final int max_no_customers = 2000;
//	// 创建Button组件
//	private Button open = new Button("开门");
//	private Button close = new Button("关门");
//	private Button add = new Button("欢迎光临");
//	private Button del = new Button("请慢走");
//	private Bank bank = new Bank();
//	private Hypermarket supermarket = new Hypermarket();
//	// 添加窗口关闭事件
//	private class WindowCloser extends WindowAdapter {
//		public void windowClosing(WindowEvent e) {
//			bank.stop();
//			supermarket.stop();
//			System.exit(0);
//		}
//	}
//	public SimulationSite() {// 构造方法,进行组件初始化和布局
//		super("SimulationSite");
//		Panel buttons = new Panel();
//		buttons.setLayout(new FlowLayout());
//		buttons.add(open);
//		open.addActionListener(this);
//		buttons.add(close);
//		close.addActionListener(this);
//		buttons.add(add);
//		add.addActionListener(this);
//		buttons.add(del);
//		del.addActionListener(this);
//		this.addWindowListener(new WindowCloser());
//		this.setLayout(new BorderLayout());
//		add("West", bank);
//		add("East", supermarket);
//		add("South", buttons);
//		validate();
//		pack();
//		show();
//		bank.start();
//		supermarket.start();
//	}
//	public void actionPerformed(ActionEvent e) {// 为单击按扭做事件监听
//		// TODO Auto-generated method stub
//		if (e.getSource() == open) {
//			bank.openDoor();
//			supermarket.openDoor();
//		} else if (e.getSource() == close) {
//			bank.closeDoor();
//			supermarket.closeDoor();
//		} else if (e.getSource() == add) {
//			bank.addAgent();
//			supermarket.addAgent();
//		} else if (e.getSource() == del) {
//			bank.retireAgent();
//			supermarket.retireAgent();
//		}
//	}
//	public static void main(String[] args) {// 本程序的入口处
//		SimulationSite sl = new SimulationSite();
//	}
//}
class ObjectQueue {// 线程队列
	private List customers = new ArrayList();
	private synchronized Object performAction(String cmd, Object obj) {// 获取对象
		if (cmd.equals("insert")) {// 增加方法的操作流程
			if (customers.isEmpty())
				customers.add(obj);
			notify();
			return null;
		} else if (cmd.equals("size")) {// 获取容量
			return new Integer(customers.size());
		} else if (cmd.equals("retrieve")) {
			while (customers.size() == 0) {
				try {
					wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			Customer c = (Customer) customers.get(0);
			customers.remove(0);
			return c;
		}
		return null;
	}
	public void insert(Customer c) {// 增加操作
		performAction("insert", c);
	}
	public int getSize() {// 获取容量
		return (((Integer) performAction("size", null)).intValue());
	}
	public Customer requestCustomer() {// 请求服务
		return (Customer) performAction("retrieve", null);
	}
}
class Customer {// 顾客类
	private Date date;// 声明一个日期类的对象
	public Customer() {// 构造方法,为date对象初始化
		date = new Date();
	}
	public int getDelayTime() {// 获取超时的时间
		return (int) (Math.random() * SimulationSite.max_customer_delay);
	}
	public long getWaitTime(Date now) {// 获取等待的时间
		return now.getTime() - date.getTime();
	}
}

 

你可能感兴趣的:(java)