`
空城旧梦why
  • 浏览: 24861 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

线程的理解

    博客分类:
  • Java
阅读更多

        对于每个学过计算机的一些基础知识的都应该知道,线程和进程。关于这两个我是这么区别的,从包含关系来说,一个进程可以包含多个线程,进程是系统分配资源的基本单位,多个线程之间的资源是共享的,而多个进程之间的资源不是共享的。

        而在软件的开发中使用线程可以提高软件的性能。

        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);
	}

}

 效果图:

 

  • 大小: 139 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics