查看线程数量
(一)在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
我们再来查看一下它的线程数:
发现鼠标虽然点击多次,但始终只有一个线程在工作。
更多
便于对代码的修改和管理,可以创建几个不同的线程来实现不同的功能,例如创建一个线程类用于画球,一个线程类用于移动球,一个线程类用于清除已经绘制过的小球。