线程的理解
对于每个学过计算机的一些基础知识的都应该知道,线程和进程。关于这两个我是这么区别的,从包含关系来说,一个进程可以包含多个线程,进程是系统分配资源的基本单位,多个线程之间的资源是共享的,而多个进程之间的资源不是共享的。
而在软件的开发中使用线程可以提高软件的性能。
Java中线程的使用有两中方式:
1、public MyThread extends Thread{
public void run() {
// 自己的代码
}
}
MyThread t = new MyThread(); // 实例化一个MyThread对象
t.start(); // 启动线程
2、public class MyThread implements Runnable {
public void run() {
// 自己的代码
}
}
Thread t = new Thread(new MyThread()); // 利用Mythread类的对象创建一个Thread对象
t.start(); // 启动线程
下面是我写的一个线程游戏,里面用了一个线程来绘制小球
主界面的类
package com.why.frame; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import com.why.thread.Ball; public class GameFrame extends JFrame implements ActionListener, Runnable { private static final long serialVersionUID = 1L; private JPanel show_panel; private Graphics2D g; private ArrayList<Ball> list = new ArrayList<Ball>(); private ArrayList<Ball> addList = new ArrayList<Ball>(); private boolean pauseFlag = false; private boolean stopFlag = false; private int width; private int height; public static void main(String[] args) { // TODO Auto-generated method stub GameFrame f = new GameFrame(); f.initUI(); new Thread(f).start(); } public void initUI() { this.setSize(new Dimension(800, 600)); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setLocationRelativeTo(null); this.setTitle("线程小游戏"); JPanel button_panel = new JPanel(new FlowLayout()); button_panel.setBackground(Color.DARK_GRAY); JButton addButton = new JButton("Add"); addButton.addActionListener(this); button_panel.add(addButton); JButton pauseButton = new JButton("Pause"); pauseButton.addActionListener(this); button_panel.add(pauseButton); JButton resumeButton = new JButton("Resume"); resumeButton.addActionListener(this); button_panel.add(resumeButton); JButton stopButton = new JButton("Stop"); stopButton.addActionListener(this); button_panel.add(stopButton); this.add(button_panel, BorderLayout.NORTH); show_panel = new JPanel(); this.add(show_panel, BorderLayout.CENTER); this.setVisible(true); width = show_panel.getWidth(); height = show_panel.getHeight(); } /** * 响应按钮被按下的事件 */ @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub String command = e.getActionCommand(); switch (command) { case "Add":// 当按下添加按钮时执行的动作 if (!pauseFlag) { stopFlag = false; Ball ball = new Ball(); // 将添加的小球暂时添加到addList列表中 addList.add(ball); } break; case "Pause":// 当按下暂停按钮时执行的动作 pauseFlag = true; break; case "Resume":// 当按下继续按钮时执行的动作 pauseFlag = false; break; case "Stop":// 当按下停止按钮时执行的动作 stopFlag = true; break; default: break; } } /** * 绘制小球 */ @Override public void run() { // TODO Auto-generated method stub //--------------------------利用双缓冲不让界面闪烁--------------------- // 创建一个缓冲图片 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 取得缓冲图片上的画笔对象 Graphics2D g2d = (Graphics2D) image.getGraphics(); //-------------------------------------------------------------------- // 消除绘图锯齿 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); this.g = (Graphics2D) show_panel.getGraphics(); while (true) { // 取得显示小球的面板上的画笔对象 if (show_panel.getWidth() != width || show_panel.getHeight() != height) { width = show_panel.getWidth(); height = show_panel.getHeight(); image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); g2d = (Graphics2D) image.getGraphics(); this.g = (Graphics2D) show_panel.getGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } g2d.clearRect(0, 0, image.getWidth(), image.getHeight()); System.gc(); // 绘制小球 for (Ball ball : list) { if (!pauseFlag) ball.move(show_panel, list); if (!stopFlag) ball.drawBall(g2d); } // 将addList中的小球添加到保存小球的列表中 if (!addList.isEmpty()) { list.addAll(addList); addList.clear(); } // 如果按下停止按钮清除小球 if (stopFlag) { list.clear(); } // 将缓冲图片画到显示小球的面板上 g.drawImage(image, 0, 0, null); try { Thread.sleep(15); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
小球类:
package com.why.thread; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Ellipse2D; import java.util.ArrayList; import java.util.Random; import javax.swing.JPanel; public class Ball { private Color color; private double x, y; private double vx; private double vy; private int radius; private Ellipse2D.Double shape; public Ball() { Random random = new Random(); this.color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)); this.vx = random.nextInt(5) + 3; this.vy = random.nextInt(5) + 3; this.x = 0; this.y = 0; this.radius = random.nextInt(30) + 20; this.shape = new Ellipse2D.Double(x, y, radius << 1, radius << 1); } /** * 绘制小球的方法 */ public void drawBall(Graphics2D g) { g.setColor(color); g.fill(shape); } /** * 移动小球位置的方法 */ public void move(JPanel panel, ArrayList<Ball> list) { x += vx; y += vy; Rectangle rect = panel.getBounds(); if (x < 0) { x = 0; vx = Math.abs(vx); } if (x > rect.getWidth() - radius * 2) { x = rect.getWidth() - radius * 2; vx = -Math.abs(vx); } if (y < 0) { y = 0; vy = Math.abs(vy); } if (y > rect.getHeight() - radius * 2) { y = rect.getHeight() - radius * 2; vy = -Math.abs(vy); } check(list); // 调用碰撞处理方法 shape.setFrame(x, y, radius << 1, radius << 1); } /** * 对小球进行碰撞检测,以及如果发生碰撞将其反弹的方法 */ private void check(ArrayList<Ball> list) { for (int i = 0; i < list.size(); i++) { // 判断小球间是否发生碰撞 Ball ball = list.get(i); if (ball == this) // 自己和自己不碰撞 continue; if (checkCollision(ball)) { // 当两球间的距离小于直径时,可认为两小球发生了碰撞 rebound(ball); ball.rebound(this); } } } private void rebound(Ball ball) { double degree = Math.atan((y + radius - ball.y - ball.radius) / (x + radius - ball.x - ball.radius));//获取自己与发生碰撞的小球之间所形成的夹角,因为夹角只能在-pi/2-pi/2之间,所以还需判断两球的x坐标之间的关系 double v = Math.sqrt(vx * vx + vy * vy); if (x + radius > ball.x + ball.radius) { // 如果自己的x坐标大于发生碰撞的小球的x坐标,由数学知识可知自己应该往正向运动 vx = Math.cos(degree) * v; vy = Math.sin(degree) * v; } else { // 如果自己的x坐标小于发生碰撞的小球的x坐标,由数学知识可知应该朝负向运动 vx = -Math.cos(degree) * v; vy = -Math.sin(degree) * v; } } /** * 检测是否发生碰撞 * @param ball 要被检测的小球 * @return 如果碰撞发生返回true,否则返回false */ private boolean checkCollision(Ball ball) { double lenx = x + radius - ball.x - ball.radius; double leny = y + radius - ball.y - ball.radius; double len = radius + ball.radius; return Math.pow(lenx, 2) + Math.pow(leny, 2) <= Math.pow(len, 2); } }
效果图: