网站首页 > java教程 正文
今天介绍一下我用多线程写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();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
继承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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
小球类,包括小球的位置、半径、颜色、运动等信息
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%256,ys%256,ys%256);
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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
控制产生随机小球,并把产生的随机小球存储在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);
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
由于三个线程中同时用到了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);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
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();
}
}
}
}
- 上一篇: 整理??款让你Java突飞猛进的小游戏
- 下一篇: Java 6 问世(java17)
猜你喜欢
- 2024-09-10 整理??款让你Java突飞猛进的小游戏
- 2024-09-10 好程序员:只有二十行代码的Java贪吃蛇游戏,Java大神之作
- 2024-09-10 用java实现简单的文字pk的小游戏,用java实现人物PK的小游戏
- 2024-09-10 java awt实现飞机小游戏(java小游戏飞机大战)
- 2024-09-10 手把手,零基础教你,JAVA开发小游戏飞翔的小鸟,资源免费领取
- 2024-09-10 来看看大佬用Java做的:微信打飞机小游戏(需求分析+代码+图片)
- 2024-09-10 不到两小时教会你用JAVA制作超级玛丽小游戏
- 2024-09-10 《我的世界》迎15周年,Java+ 基岩版游戏国区五折售44.5元
- 2024-09-10 无聊的周末用Java写个扫雷小游戏(java编写扫雷)
- 2024-09-10 程序员用Java实现扫雷小游戏,引来广大网友狂点赞,直呼炸天
你 发表评论:
欢迎- 最近发表
-
- java8的stream使用小示例(java stream的用法)
- Java 中的 Lambda 表达式深入解析:从语法糖到高阶函数
- 实战解析Android架构设计原则(android的架构)
- 搭建mcp服务器用java17,可是项目开发用的是java8怎么实现?
- Java Stream:集合处理的api(java集合流操作)
- Java 8新特性全面剖析:让编程变得更简单优雅
- Java 8新特性全面解析与最佳实践:掌握未来编程的艺术
- Java 8日期时间API新特性揭秘与深度解析
- Java 8 Stream API 详解(java.stream)
- Java机器学习库(Java ML)(二、聚类)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)