对于每个学过计算机的一些基础知识的都应该知道,线程和进程。关于这两个我是这么区别的,从包含关系来说,一个进程可以包含多个线程,进程是系统分配资源的基本单位,多个线程之间的资源是共享的,而多个进程之间的资源不是共享的。
而在软件的开发中使用线程可以提高软件的性能。
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);
}
}
效果图: