线程应用实例
实例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(); } }