今天介绍一下我用多线程写JAVA 程序时需要注意的地方:
首先给大家看一下效果图:(大家也可以找一个其他的背景图)黑球是我可以用鼠标控制的,其他小球则是随机产生,当我的小球和随机小球球心距离小于半径时便可以将随机小球消灭,同时控制随机小球数量不超过5个。线程包括:产生随机小球的线程inThread、显示小球的线程outThread、当满足消灭小球条件时将小球移除队列的线程clearThread.
实现代码如下:
public class First {
public void FirstUI(){
JFrame firFra=new JFrame();
firFra.setSize(800,800);
firFra.setLocationRelativeTo(null);
firFra.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//FlowLayout flow=new FlowLayout();
//firFra.setLayout(flow);
firFra.setVisible(true);
Graphics g=firFra.getGraphics();
Firlistener firlis=new Firlistener(g);
firFra.addMouseListener(firlis);
firFra.addMouseMotionListener(firlis);
ImageIcon pic=new ImageIcon("C:\\Users\\user\\Desktop\\1.jpg");
Image dd=pic.getImage();
g.drawImage(dd,0,0,firFra.getWidth(),firFra.getHeight(),firFra);
}
public static void main(String []args){
First fir=new First();
fir.FirstUI();
}
}
继承MouseAdapter类,这样就可以只重写需要重写的函数,而不用把MouseListener, MouseWheelListener, MouseMotionListener单个类的函数都重写一遍,比如本程序只用到mouseClicked(MouseEvent e)、mouseDragged(MouseEvent e)两个函数,便不用把其他没用到的函数都重写一次。
public class Firlistener extends MouseAdapter{
Graphics g;
inThread in;
int count = 0;//
private ArrayList<Ball> listBall = new ArrayList<Ball>();
private Ball ball=new Ball();
outThread out;
public Firlistener(Graphics g){
this.g=g;
}
//创建小球,显示小球
public void mouseClicked(MouseEvent e){
ball.x=e.getX();
ball.y=e.getY();
Ball bb=new Ball();
listBall.add(bb);
if(in==null){
in=new inThread(listBall);
in.start();
out=new outThread(listBall,g,ball);
out.start();
clearThread clc=new clearThread();
clc.setclear(listBall, ball);
clc.start();
}
}
public void mouseDragged(MouseEvent e){
ball.x=e.getX()-60;
ball.y=e.getY()-60;
// ball.size=60;
out.setout(listBall, g, ball);
}
}
小球类,包括小球的位置、半径、颜色、运动等信息
public class Ball {
private int vx, vy, n = 0;
public int x,y,size;
Random ran = new Random();
Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256));
public void setdata() {
x = ran.nextInt(620) 40;
y = ran.nextInt(620) 40;
size = ran.nextInt(40) 20;
vx = ran.nextInt(10);
vy = ran.nextInt(10);
vx = 5 - vx;
vy = 5 - vy;
}
public void setball(int x, int y, int size) {
this.x = x;
this.y = y;
this.size = size;
}
public void paintball(Graphics g) {
// Color color=new Color(ys%6,ys%6,ys%6);
g.setColor(color);
g.fillOval(x, y, size, size);
// System.out.println("x:" x "********y:" y "*****size:" size);
}
public void drawball(Graphics g) {
if (n == 0) {
setdata();
n ;
}
if (x <= 40 || x >= 760)
vx = -vx;
if (y <= 40 || y >= 760)
vy = -vy;
x = x vx;
y = y vy;
//Color color = new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256));
g.setColor(color);
g.fillOval(x-size, y-size, size, size);
}
public int getx() {
return x;
}
public int gety() {
return y;
}
public int getsize() {
return size;
}
}
控制产生随机小球,并把产生的随机小球存储在listBall队列中,由于这里的listBall只是类似于地址指针,并没有具体的存储空间,当监听器中的listBall将地址传过来便可以进行操作了,这样可以保证所有线程操作的listBall队列是同一个数据、当一个线程将数据改变之后可以保证数据同步。同理,在outThread、clearThread线程中也是用的同样的方法保证数据同步。
public class inThread extends Thread{
private ArrayList<Ball> listBall;
public inThread(ArrayList<Ball> listBall){
this.listBall=listBall;
}
public void run(){
Ball bb=new Ball();
listBall.add(bb);
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(listBall.size()<=3){
Ball ball=new Ball();
listBall.add(ball);
}
}
}
}
由于三个线程中同时用到了listBall队列,当两个线程都要调用这个数据时就会出错,为了保证其中一个线程调用时其他程序不能调用listBall,需要用到synchronized (listBall)对listBall进行锁定,保证当本线程调用时其他线程无法使用listBall队列。同理,clearThread线程也有同样的处理方法。
public class outThread extends Thread{
private ArrayList<Ball> listBall;
private Ball ball;
private Graphics g;
public outThread(ArrayList<Ball> listBall,Graphics g,Ball ball){
this.listBall=listBall;this.ball=ball;
this.g=g;
}
public void setout(ArrayList<Ball> listBall,Graphics g,Ball ball){
this.listBall=listBall;this.ball=ball;
this.g=g;
}
@Override
public void run() {
int big=0;
while(true){
try {
Thread.sleep(40);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ImageIcon pic=new ImageIcon("C:\\Users\\user\\Desktop\\1.jpg");
Image dd=pic.getImage();
g.drawImage(dd,0,0,800,800,null);
//g.setColor(Color.WHITE);
//g.fillRect(0, 0, 800, 800);
synchronized (listBall) {
for(int i=0;i<listBall.size();i ){
Ball bal = listBall.get(i);
//改变控制球的大小
if(big==1){
ball.setball(ball.getx(), ball.gety(), ball.getsize()-1);
if(ball.getsize()<=40){big=0;}
}else if(big==0){
ball.setball(ball.getx(), ball.gety(), ball.getsize() 1);
if(ball.getsize()>=120){big=1;}
}
bal.drawball(g);
}
}
ball.paintball(g);
}
}
}
public class clearThread extends Thread {
private ArrayList<Ball> listBall;
private Ball ball;
public void setclear(ArrayList<Ball> listBall, Ball ball) {
this.listBall = listBall;
this.ball = ball;
}
public void run() {
while (true) {
// if(listBall!=null){
synchronized (listBall) {
for (int i = 0; i < listBall.size(); i ) {
Ball bal = listBall.get(i);
System.out.println("absx:" Math.abs(bal.getx() - ball.getx()));
System.out.println("absy:" Math.abs(bal.gety() - ball.gety()));
if (Math.abs(bal.getx() - ball.getx()) <= ball.getsize()
&& Math.abs(bal.gety() - ball.gety()) <= ball.getsize()) {
System.out.println("ball.x=" bal.getx() "ball.y" bal.gety());
listBall.remove(bal);
}
}
// }
}
try {
Thread.sleep(40);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved