最近在搞一个弹球游戏,其中,用到了Java多线程的应用,首先,先说一下,什么叫做线程。或许大家都知道进程是什么,打开电脑的任务管理器,可以看到,里面有进程这个选项,非常明显,进程就是一个程序,而每个程序,有由多个线程组成。好了,这样说的不清不楚的,那么好,我用一个弹球小游戏来解释一下,那样可能大家会更容易理解些。
import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * 游戏界面类 * * @author Administrator * */ public class GameUI extends javax.swing.JFrame { private static GameUI UI; private java.awt.Graphics g; private MyListener ml; public javax.swing.JLabel text_field; public javax.swing.JProgressBar pBar; private String command; public java.util.ArrayList<MyThread> list = new java.util.ArrayList<MyThread>(); private javax.swing.JToggleButton button; public static void main(String args[]) { UI = new GameUI(); UI.initUI(); } /** * 初始化窗体的方法 */ public void initUI() { // 设置标题 this.setTitle("是高手就坚持100s"); // 设置大小 this.setSize(610, 635); // 设置关闭是退出程序 this.setDefaultCloseOperation(3); // 设置打开窗体时在屏幕中间显示 this.setLocationRelativeTo(null); // 设置窗体的流式布局管理器 this.setLayout(new java.awt.FlowLayout()); // 设置窗体背景颜色 this.getContentPane().setBackground(java.awt.Color.black); // 创建文本标签对象 text_field = new javax.swing.JLabel(); javax.swing.JLabel lable = new javax.swing.JLabel("时 间 :"); // 设置文本标签前景颜色 lable.setForeground(java.awt.Color.red); text_field.setForeground(java.awt.Color.red); // 创建进度条对象 pBar = new javax.swing.JProgressBar(0, 330); // 创建按钮对象 button = new javax.swing.JToggleButton(); button.setMargin(new Insets(0, 0, 0, 0)); button.setIcon(new javax.swing.ImageIcon("images/Pause.gif")); button.setActionCommand("暂停"); // 通过匿名内部类来创建动作监听器 java.awt.event.ActionListener button_listener = new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { String com = e.getActionCommand(); if (com.equals("暂停")) { button.setMargin(new Insets(0, 0, 0, 0)); button .setIcon(new javax.swing.ImageIcon( "images/start.gif")); button.setActionCommand("继续"); for (int i = 0; i < list.size(); i++) { list.get(i).PauseThread(); } } if (com.equals("继续")) { button.setMargin(new Insets(0, 0, 0, 0)); button .setIcon(new javax.swing.ImageIcon( "images/Pause.gif")); button.setActionCommand("暂停"); for (int i = 0; i < list.size(); i++) { list.get(i).ContinueThread(); } } } }; button.addActionListener(button_listener); this.add(button); this.add(lable); this.add(pBar); this.add(text_field); // 的到菜单条 javax.swing.JMenuBar bar = creatMenuBar(); // 为窗体设置菜单条 this.setJMenuBar(bar); // 设置窗体的可见性 this.setVisible(true); } /** * 创建菜单条的方法 * * @return */ public javax.swing.JMenuBar creatMenuBar() { // 创建菜单条对象 javax.swing.JMenuBar bar = new javax.swing.JMenuBar(); // 创建菜单对象 javax.swing.JMenu menu_menu = new javax.swing.JMenu("菜单"); javax.swing.JMenu difficulty_menu = new javax.swing.JMenu("难度"); javax.swing.JMenu help_menu = new javax.swing.JMenu("帮助"); // 创建菜单选项对象 javax.swing.JMenuItem star_item = new javax.swing.JMenuItem("开始"); javax.swing.JMenuItem exit_item = new javax.swing.JMenuItem("退出"); javax.swing.JMenuItem help_item = new javax.swing.JMenuItem("游戏说明"); javax.swing.JMenuItem about_item = new javax.swing.JMenuItem("关于"); // 创建单选选项 javax.swing.JRadioButtonMenuItem easy_item = new javax.swing.JRadioButtonMenuItem( "简单"); javax.swing.JRadioButtonMenuItem middle_item = new javax.swing.JRadioButtonMenuItem( "中等"); javax.swing.JRadioButtonMenuItem hard_item = new javax.swing.JRadioButtonMenuItem( "困难"); // 创建一个按钮组 javax.swing.ButtonGroup group = new javax.swing.ButtonGroup(); // 将单选按钮添加到按钮组中 group.add(easy_item); group.add(middle_item); group.add(hard_item); // 将单选按钮添加到菜单中 difficulty_menu.add(easy_item); difficulty_menu.add(middle_item); difficulty_menu.add(hard_item); // 通过匿名内部类来创建动作监听器 ActionListener listener = new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { command = e.getActionCommand(); // 如果选择开始,则创建线程对象 if (command.equals("开始") && list.size() == 0) { creatBall(20, 1); } // 如果选择退出按钮,则退出程序 if (command.equals("退出")) { System.exit(0); } // 如果选择简单按钮 if (command.equals("简单") && list.size() == 0) { creatBall(20, 1); } // 如果选择中等按钮 if (command.equals("中等") && list.size() == 0) { creatBall(50, 2); } if (command.equals("困难") && list.size() == 0) { creatBall(40, 2); } if (command.equals("游戏说明")) { javax.swing.JOptionPane.showMessageDialog(null, "移动鼠标,用挡板接球,如果接不住,就算输了……\n游戏可以选择难度,包括简单、中等、困难"); } if (command.equals("关于")) { javax.swing.JOptionPane .showMessageDialog(null, "这是一个用Java编写的小游戏……\n制作人:沈冠军\n时间:2010年8月\n版权所有,翻版必究!"); } } }; // 添加动作监听器 star_item.addActionListener(listener); exit_item.addActionListener(listener); easy_item.addActionListener(listener); middle_item.addActionListener(listener); hard_item.addActionListener(listener); help_item.addActionListener(listener); about_item.addActionListener(listener); // 将菜单选项对象添加到菜单对象上 menu_menu.add(star_item); menu_menu.add(exit_item); help_menu.add(help_item); help_menu.add(about_item); // 将菜单对象添加到菜单条上 bar.add(menu_menu); bar.add(difficulty_menu); bar.add(help_menu); // 返回菜单条对象 return bar; } /** * 创建线程对象的方法 * * @param speed * :速度 * */ public void creatBall(int speed, int num) { java.util.Random ran = new java.util.Random(); if (ml == null) { g = UI.getGraphics(); ml = new MyListener(g); UI.addMouseListener(ml); UI.addMouseMotionListener(ml); } for (int i = 0; i < num; i++) { int x = ran.nextInt(600) + 10; int y = ran.nextInt(300) + 100; MyThread th = new MyThread(g, ml, UI, x, y, speed); list.add(th); th.start(); } } /** * 得到命令的方法 */ public String getCommand() { return command; } }import java.awt.Color; import javax.swing.JOptionPane;
/** * 线程类 * * @author Administrator * */ public class MyThread extends Thread { private int width = 20, height = 20; private int x, y; private java.awt.Graphics g; private GameUI UI; private boolean isexist = true; private MyListener listener; private int speed; private int x1 = 12, y1 = 12; private long start, end; private long last_time; private int response; private boolean isFinish = true; private boolean isPause = true; private java.util.ArrayList<MyThread> list; private float value = 320; private java.awt.Color color = java.awt.Color.blue; /* * 重写构造器 */ public MyThread(java.awt.Graphics g, MyListener listener, GameUI UI, int x, int y, int speed) { this.g = g; this.UI = UI; this.x = x; this.y = y; this.speed = speed; this.listener = listener; } /* * (non-Javadoc)重写run的方法 * * @see java.lang.Thread#run() */ public void run() { drawOval(); } /** * 创建线程的方法 */ public void drawOval() { start = System.currentTimeMillis(); while (isFinish) { while (isPause) { synchronized(this.g){ // 画一个圆 g.setColor(java.awt.Color.black); g.fillOval(x, y, width, height); x += x1; y += y1; getColors(); g.setColor(color); g.fillOval(x, y, width, height); } int x2 = listener.getX(); if (x > 580) { x1 = -12; } if (x < 10) { x1 = 12; } if (y < 90) { y1 = 12; } if (y > 595 && x > x2 && x < x2 + 100) { y1 = -12; } if (y > 630) { if (isexist) { isAgain(); } stopThread(); } try { Thread.sleep(speed); value -= 0.1; } catch (Exception ef) { ef.printStackTrace(); } // 将前一次画的清除掉 end = System.currentTimeMillis(); last_time = 100 - (end - start) / 1000; UI.text_field.setText(last_time + "s"); UI.pBar.setValue((int) value); if (last_time == 0) { list = UI.list; for (int j = 0; j < list.size(); j++) { // 停在线程,并且去掉最后一个圆 list.get(j).stopThread(); list.get(j).fadeOval(); } stopThread(); showDialog(); } } } } /** * 线程结束时消去最后一个圆的方法 */ public void fadeOval() { g.setColor(java.awt.Color.black); g.fillOval(x, y, width, height); } /** * 重来对话框的处理方法 */ public void isAgain() { isexist = false; list = UI.list; System.out.println(list.size()); for (int j = 0; j < list.size(); j++) { // 停在线程,并且去掉最后一个圆 list.get(j).stopThread(); list.get(j).fadeOval(); } Object[] options = { "是", "否" }; String command = UI.getCommand(); response = JOptionPane.showOptionDialog(null, "哈哈,你输了!不要灰心\n坚持就是胜利,是否再来一次?", null, JOptionPane.YES_OPTION, JOptionPane.NO_OPTION, null, options, null); System.out.println(response); if (response == 0) { if (command.equals("简单") || command.equals("开始")) { AgainThread(); if (list.size() != 0) { // 现将原来的对象从队列中移除 list.removeAll(list); UI.creatBall(20, 1); } } if (command.equals("中等")) { AgainThread(); if (list.size() != 0) { list.removeAll(list); UI.creatBall(50, 2); } } if (command.equals("困难")) { AgainThread(); if (list.size() != 0) { list.removeAll(list); UI.creatBall(40, 2); } } } // 如果点击关闭,则将线程对象从队列中移除 if (response == -1 || response == 1) { list.removeAll(list); } } /** * 停止线程的方法 */ public void stopThread() { isFinish = false; isPause = false; } /** * 暂停线程的方法 */ public void PauseThread() { isPause = false; } /** * 继续线程的方法 */ public void ContinueThread() { isPause = true; } /** * 是否重来的方法 */ public void AgainThread() { isFinish = true; isPause = true; } public void getColors() { if (x % 2 == 0 && y % 2 == 0) { color = java.awt.Color.green; } if (x % 2 == 0 && y % 2 != 0) { color = java.awt.Color.red; } if (x % 2 != 0 && y % 2 != 0) { color = java.awt.Color.orange; } if (x % 2 != 0 && y % 2 != 0) { color = java.awt.Color.yellow; } } public void showDialog() { javax.swing.JOptionPane .showInputDialog("好样的,你是真的高手,\n恭喜你坚持了100s\n请输入您的大名"); } }
import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import javax.swing.JFrame; /** * 鼠标监听器的类 * * @author Administrator * */ public class MyListener extends java.awt.event.MouseAdapter { private java.awt.Graphics g; private int x = 5, y = 620; private int width = 100, height = 10; public MyListener(java.awt.Graphics g) { this.g = g; } public void mouseMoved(MouseEvent e) { // 设置画布对象颜色 synchronized (this.g) { g.setColor(java.awt.Color.black); g.fillRect(x, y, width, height); x = e.getX(); g.setColor(java.awt.Color.green); g.fillRect(x, y, width, height); } } /** * 得到x的方法 * * @return:x */ public int getX() { return x; } }
界面效果图:
好了,大家看到了,线程的作用就是在一个程序中可以同时做不、同的事,就像上面的 弹球游戏,它可以在画矩形的同时画圆,两个可以同时发生,当选择难度时可以看都,可以同时画多个球。