Java线程系列(二)线程小球的优化,减少线程数

查看线程数量

(一)在eclipse显示台下有虚拟机的打开路径
在这里插入图片描述
(二)在电脑文件中找到改目录下的文件点开
在这里插入图片描述
(三)运行程序时就能看到所进行的线程了

在这里插入图片描述

原方法分析,找到弊端

在线程系列(一)中介绍了两种实现线程的方法,一个是继承Thread类,一个是实现Runnable接口。但程序那样写时其实有一个弊端,就是没画一次图形线程都会启动一次,若画多个图形,线程会启动多次。
在这里插入图片描述

其实这没有必要。
我们对其改进一下,画图只用一个线程实现试试。

改进思路

这里需要四个类:界面类,小球类,监听器类和线程类。
界面类:包含主函数,是程序的入口。继承JFrame,实现窗体的初始化,再从窗体上获取画笔。
小球类:包含小球的属性(位置,速度,颜色,大小)和方法(绘制小球,清除小球,移动小球)。建立一个带有小球属性的参数的构造方法便于初始化小球。
监听器类:实现鼠标监听器,重写所有的方法,在鼠标点击时获取小球,并将其存入队列。
线程类:实现Runnable接口,重写run()方法。把小球从队列中取出来,清除,移动,绘制。
然后在主函数中创建监听器类的对象,给窗体加上鼠标监听器;创建一个线程类的对象,把监听器中的存储小球的队列存入线程类;创建一个线程并启动它。

代码实现

界面类

import java.awt.Graphics;

import javax.swing.JFrame;

public class UI extends JFrame{
		//主函数
	public static void main(String[] args) {
		new UI().Initl();	
	}
	
	public void Initl() {
		setTitle("改进后的小球");			//设置标题
		setSize(800,600);				//设置窗体的大小
		setDefaultCloseOperation(3);	//设置关闭选项
		setLocationRelativeTo(null);	//设置窗体位置居中
		setVisible(true);				//设置窗体可见
		
		Graphics g=getGraphics();			//从窗体上获取画笔
		
		BallListener bl=new BallListener();//创建监听器对象
		addMouseListener(bl);				//给窗体加上鼠标监听器
		
		ThreadBall threadball=new ThreadBall(g);//创建一个线程类对象
		threadball.ballList=bl.ballList;	//把监听器中的队列传给线程类
		
		Thread th=new Thread(threadball); //创建线程
		th.start();							//启动线程
		
	}
}

小球类

import java.awt.Color;
import java.awt.Graphics;

public class Ball {
	
	int x,y,speedx,speedy,size;
	Color color;
	//小球的构造方法
	public Ball(int x,int y,int size,int speedx,int speedy,Color color) {
		this.x=x;
		this.y=y;
		this.size=size;
		this.speedx=speedx;
		this.speedy=speedy;
		this.color=color;
	}
	//画球
	public void drawBall(Graphics g) {
		g.setColor(color);
		g.fillOval(x, y, size, size);
	}
	//移动球
	public void move() {
		if(x<=300) {
			x=x+speedx;
			y=y-speedy;
		}else {
			x=x+speedx;
			y=y+speedy;
		}	
	}
	//清除球
	public void cleanBall(Graphics g) {
		g.setColor(new Color(238,238,238));//背景板的颜色
		g.fillOval(x, y, size, size);
	}
}

监听器类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;

public class BallListener implements MouseListener{
	//创建用来存储小球的队列
	ArrayList<Ball> ballList = new ArrayList<> ();
	
	@Override
	public void mouseClicked(MouseEvent e) {
		int x=e.getX();			//获取小球的坐标
		int y=e.getY();
		Random ran=new Random();
	
		Color color=new Color(ran.nextInt(Integer.MAX_VALUE));
		
		Ball ball=new Ball(x,y,50,1,2,color);
		
		ballList.add (ball);	//小球入队列
	}

	@Override
	public void mousePressed(MouseEvent e) {}

	@Override
	public void mouseReleased(MouseEvent e) {}

	@Override
	public void mouseEntered(MouseEvent e) {}

	@Override
	public void mouseExited(MouseEvent e) {}

}

线程类

import java.awt.Graphics;
import java.util.ArrayList;

public class ThreadBall implements Runnable{
	
	ArrayList<Ball> ballList ;
	Graphics g;
	
	//构造方法
	public ThreadBall(Graphics g) {
		// TODO Auto-generated constructor stub
		this.g=g;
	}
	//重写run方法
	@Override
	public void run() {
		while(true) {
			for(int i = 0; i < ballList.size (); i++){ // 取出球
				Ball ball = ballList.get (i); // 调用小球的方法 执行 
				ball.cleanBall (g); 
				ball.move (); 
				ball.drawBall (g);
			}
			try {
				Thread.sleep (15); 
				} catch (InterruptedException e) {
					e.printStackTrace (); 
					}
		}
	}
}

程序运行效果如下:

小球2

我们再来查看一下它的线程数:
在这里插入图片描述
发现鼠标虽然点击多次,但始终只有一个线程在工作。

更多

便于对代码的修改和管理,可以创建几个不同的线程来实现不同的功能,例如创建一个线程类用于画球,一个线程类用于移动球,一个线程类用于清除已经绘制过的小球。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值