P04 并发小球V1 V2.1

目录

线程游戏V1——多线程

目标效果

一 Ball类

​ 二 BallThread类

三 UIListenner类

​ 四 GameUI类

 运行结果

问题分析

线程游戏V2——三线程

目标效果

新增MoveThread线程实现类

修改监听器类UIListenner代码

运行结果

问题分析

问题2代码实现

V2版本如何实现不同的小球随机方向移动的

最终代码


线程游戏V1——多线程

目标效果

多线程实现,每点击一次鼠标就启动一个线程,单个线程实现重复绘制小球,绘制的小球所有属性相同。

一 Ball类

属性:

 * 坐标xy,尺寸size,移动速度speedx,speedy,球的颜色

方法:

 * 构造方法Ball:构造所有属性

 * 封装方法:所有属性的get和set方法

 * 绘制方法:draw把球画出来

 * 移动方法:move小球的移动

 二 BallThread类

线程实现类,实现Runnable接口,传入球对象和画笔,重写run方法,写个死循环,实现一直绘制随机大小位置颜色尺寸的圆

三 UIListenner类

继承MouseAdapter,将监听器和线程结合,实现每次鼠标按下时刻创建线程对象,启动线程,在鼠标按下的位置画圆

 四 GameUI类

继承JFrame,写一个界面,传入两个监听器实现类对象

 运行结果

问题分析

看UIListenner类中的以下代码

 

原本的目的是:每次按下鼠标都启动一个线程,绘制无数个小球,这无数个小球应该有相同的属性(尺寸,速度,颜色)

但是看运行结果,同一个线程画出的小球颜色是随机的,出现了线程不安全问题

主要原因:画笔g是从窗体上获取的,绘制图像的所有画笔都是同一个对象g,而鼠标每次点击,都会随机创建一个color设置给g,造成了画笔颜色更改。

如果只按一次鼠标,就不会出现线程安全问题,单一线程绘制出来的所有小球都是相同的。

点击两次鼠标的效果:

 解决方式:去掉判断,每次按下鼠标都获取一次画笔

这样单个线程画出的小球都有相同的属性

 

但是这样频繁的获取画笔会造成资源的浪费。可以用下面的解决方法,实现V2。

线程游戏V2——三线程

鼠标监听器相当于一个线程,点击一次在列表中新增一个小球对象

 

目标效果

三个线程,一个线程用于绘制,一个线程用于移动,监听器用于往列表中添加球对象

新增MoveThread线程实现类

 

修改BallThread类代码

删除绘制小球的代码。

修改监听器类UIListenner代码

修改后就不是每次点击鼠标都启动一个线程了。只在第一次按下鼠标时获取画笔,创建两个线程。

运行结果

问题分析

问题1:ArrayList不支持并发,BallThread类的run方法中对balls列表进行遍历绘制,MoveThread类的run方法也在对balls列表进行遍历移动,UIListenner类中鼠标每点击一次就给列表新增一个球。三个线程都对同一个列表操作,一边遍历一遍新增,迅速点击鼠标就会出现问题。

问题1解决方法:把两个线程实现类的run方法中的增强for循环改为普通for循环既可

问题2:点击鼠标次数很多很多时,发现小球的绘制移动速度下降

问题2解决方法:限制每个线程绘制小球的上限,比如200个。

问题2代码实现

创建多个队列,控制每个队列只add200个小球对象,每个队列用一个BallThread线程绘制,一个MoveThread线程移动。

V2版本如何实现不同的小球随机方向移动的

如果只点击一次鼠标 队列中只有一个球,BallThread线程会不断的绘制这个球,MoveThread线程会不断的移动球,由于遍历的都是同一个队列,视觉上就是一个球在不断的移动

如果点击两次鼠标,队列中有两个球,ball01和ball02,有不同的颜色尺寸位置和速度

对于ball01来说,每次移动的距离都是创建ball01时随机生成的speedx01和speedy01,是不变的,绘制的颜色尺寸也是创建ball01时随机生成的,也不会变。

对于ball02来说,每次移动的距离都是创建ball01时随机生成的speedx02和speedy02,也是不变的。绘制的颜色尺寸也是创建ball02时随机生成的,也不会变。

但是speedx01和speedx02不相等;speedy01和speedy02也不相等

视觉上的效果就是ball01和ball02以不同的速度移动

对于balls列表中的某个特定的ball对象来说,它的所有属性都是固定的,两个线程在处理这个特定的ball对象时,就可以实现这个ball的无限次被绘制和无限次被移动,且每次画出的小球是一样的,移动的距离也是一样的。

最终代码

 

package project3.lry0428V22;import java.awt.*;public class Ball {//private防止外部调用,写为私有的private int x, y, size, speedx, speedy;//speedx和speedy的正负可以代表方向private Color color;/*** 构造方法 构造所有的属性* @param x* @param y* @param size* @param speedx* @param speedy* @param 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;}/*** 绘制方法;把球画出来* @return*/public void draw(Graphics g){g.setColor (color);g.fillOval (x, y, size, size);//球的坐标是外切矩形左上角,size是矩形的宽高}/*** 球的移动** @return*/public void move(){// 要注意移动边界,坐标超过边界,速度反向// 球的坐标是外切矩形左上角,size是矩形的宽高,所以要-sizeif(x < 0 || x > 800 - size){speedx = -speedx;}if(y < 0 || y > 800 - size){speedy = -speedy;}x += speedx;//x移动speedxy += speedy;//y移动speedy}//以下为封装方法public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public int getSpeedx() {return speedx;}public void setSpeedx(int speedx) {this.speedx = speedx;}public int getSpeedy() {return speedy;}public void setSpeedy(int speedy) {this.speedy = speedy;}public Color getColor() {return color;}public void setColor(Color color) {this.color = color;}}

 

package project3.lry0428V22;import java.awt.*;
import java.util.ArrayList;/*** 在V21的基础上修改BallThread的run方法中的增强for循环为普通for循环**/public class BallThread implements Runnable {//绘制球需要球对象以及画笔private ArrayList<Ball> balls;//队列存入小球private Graphics g;//构造方法,用于把球对象和画笔传进来public BallThread(ArrayList<Ball> balls, Graphics g){this.balls = balls;this.g = g;}@Overridepublic void run(){while(true){//死循环try {// 线程运行很快,休眠让人眼可以看见花球的过程,大概30ms就可以Thread.sleep (30);} catch (InterruptedException e) {e.printStackTrace ();}for (int i = 0; i < balls.size(); i++) {Ball ball = balls.get(i);ball.draw(g);}}}
}

 

package project3.lry0428V22;import javax.swing.*;/*** V22版本实现每个线程只能处理200个小球*/
public class GameUI extends JFrame {private UIListenner uiListenner = new UIListenner();//创建监听器对象//构造方法,进行界面初始化public GameUI() {initUI();uiListenner.setGui(this);//把窗体传给监听器}//界面初始化void initUI() {this.setTitle("线程游戏");this.setSize(800,800);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(3);this.setVisible(true);this.addMouseListener(uiListenner);//给窗体添加鼠标监听器,传入监听器对象uiListenner,实现拖动监听this.addMouseMotionListener(uiListenner);//给窗体添加鼠标运动监听器,传入监听器对象uiListenner,实现按下监听}public static void main(String[] args) {new GameUI();}}

 

package project3.lry0428V22;import java.util.ArrayList;
/*** 在V21的基础上修改MoveThread的run方法中的for循环为普通for循环**/
public class MoveThread implements  Runnable{private ArrayList<Ball> balls;//存多个球,队列//构造方法public MoveThread(ArrayList<Ball> balls){this.balls=balls;}@Overridepublic void run(){//遍历队列while(true){try {Thread.sleep (30);//休眠30ms,肉眼可见} catch (InterruptedException e) {e.printStackTrace ();}for(int i = 0; i < balls.size (); i++){Ball ball = balls.get (i);ball.move();}}}
}

 

package project3.lry0428V22;import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Random;public class UIListenner extends MouseAdapter {//继承MouseAdapter不用重写所有的方法private GameUI gui;//直接传gui,免得还要传画笔这种小弟。为了方便传参数,不用.来调用,写个set方法。放在最后Graphics g;Random ran = new Random();//ArrayList不支持并发ArrayList<Ball> balls1 = new ArrayList<>();ArrayList<Ball> balls2 = new ArrayList<>();ArrayList<Ball> balls3 = new ArrayList<>();//每次鼠标鼠标按下就创建一个线程@Overridepublic void mousePressed(MouseEvent e) {//鼠标按下就获取画笔if (g == null) {//加这个判断是因为,不要每次按下鼠标都要获取画笔,因为都是同一个窗体上获取的画笔,每次都拿是浪费资源g = gui.getGraphics();//UI类中窗体已经传过来了BallThread ballThread1 = new BallThread(balls1,g);BallThread ballThread2 = new BallThread(balls2,g);BallThread ballThread3 = new BallThread(balls3,g);MoveThread moveThread1 = new MoveThread(balls1);MoveThread moveThread2 = new MoveThread(balls2);MoveThread moveThread3 = new MoveThread(balls3);new Thread(ballThread1).start();//启动绘制线程new Thread(ballThread2).start();//启动绘制线程new Thread(ballThread3).start();//启动绘制线程new Thread(moveThread1).start();//启动移动线程new Thread(moveThread2).start();//启动移动线程new Thread(moveThread3).start();//启动移动线程}//准备球的数据:坐标xy,尺寸size,speedx,speedy,颜色int x = e.getX();int y = e.getY();int size = ran.nextInt(50) + 25;int speedx = 50;/*ran.nextInt(5) + 1;*/int speedy = 50;/*ran.nextInt(5) + 1;*/Color color = new Color(ran.nextInt(Integer.MAX_VALUE));//颜色取值是整数的最大值Ball ball = new Ball(x,y,size,speedx,speedy,color);//创建球对象,把上面的参数传进来if (balls1.size() < 200) {balls1.add(ball);//将每次创建的球加到列表中}else if (balls2.size() < 200) {balls2.add(ball);}else if (balls3.size() < 200) {balls3.add(ball);}//        BallThread ballThread = new BallThread(ball,g);//每次鼠标按下就创建一个线程,给线程传入球和画笔
//        new Thread(ballThread).start();//启动线程}//鼠标拖动@Overridepublic void mouseDragged(MouseEvent e) {}public void setGui(GameUI gui) {//为了方便传参数,不用.来调用,写个set方法this.gui = gui;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/47135.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用python写的判断是否是水仙花数

水仙花数是百位的3次方十位的3次方个位的3次方原数 while循环 i100while i<1000:a100i//100 #//用于取整&#xff0c;a100得到的值是百位的a10(i//10)%10 #%用于取余&#xff0c;a10得到的值是十位的ai%10 #a得到的值是个位的if(ia100**3a10**3a**3): #判断是…

固定管线shader编写:基本属性

欢迎转载&#xff01;转载时请注明出处&#xff1a; http://write.blog.csdn.net/postedit/50753008 shader 部分介绍&#xff1a; properties&#xff1a;属性部分 material&#xff1a;材质部分 lighting&#xff1a; 启用光照&#xff08;顶点光照&#xff09; settexture :…

计算机图形学(2):OpenGL画球体

参考文章 配置OpenGL环境看上一篇文章 效果图&#xff1a; main.cpp&#xff1a; #include "Dependencies/glew/glew.h" #include "Dependencies/GLFW/glfw3.h"#include "Dependencies/glm/glm.hpp" #include "Dependencies/glm/gtc/m…

MATLAB | 一起来感受数学之美叭

前两天去观摩了MATHWORKS官方举办的Mathematics is beautiful数学之美投票比赛&#xff0c;见到了很多非常惊艳的作品&#xff0c;在这里分享给大家让大家一同感受大神们的创造力&#xff0c;接下来由我来做全程解说。 虽然看起来代码都写好了&#xff0c;&#xff0c;&#x…

由绘制python蟒蛇实例来整体掌握turtle绘图方法

经典案例&#xff1a;python蟒蛇的绘制 话不多说&#xff0c;直接上代码&#xff0c;先整体感知turtle图形绘制。 print("python蟒蛇的绘制") import turtle as t#引入turtle库函数来实现绘图功能 #并使用import...as...使turtle起个小名为t&#xff0c;使代码简洁 t…

七夕节快到了,教你用MATLAB绘制blingbling的大钻石

1效果 2程序说明 其实非常简单&#xff0c;只需要计算出各个顶点位置&#xff0c;并用fill3绘制一个个面出来即可&#xff0c;为了钻石的色彩更加丰富&#xff0c;我们用light函数设置了光照并为fill3创建出的PATCH对象设置了以下属性。 FaceAlpha 面透明度EdgeAlpha 边透明度…

520还在画玫瑰?教你用MATLAB画个玫瑰花球

效果如下&#xff1a; 原理 玫瑰绘制 要画花球我们要先会绘制一朵花&#xff1a; 如何画一朵花可以看看这篇&#xff1a;MATLAB 3D玫瑰花绘制 三维坐标变化 主要用下面的坐标变化方法&#xff1a; 正十二面体球 想像这里有一个正十二面体球&#xff0c;我们把每一面放上…

Android应用开发-学生信息管理系统

设计目的 1、网上很少有关于SQLite简单综合项目的测试APP。 2、把自己所学的部分UI综合一下&#xff0c;希望能给新手一些帮助。 涉及知识点 1、包括SQLite的增删查找等功能。查找中加入了“模糊搜索”的功能。 2、RecyclerView展示 3、SharedPreference保存密码&#xff0c…

基于Android的班级管理APP的设计与实现

选题背景 在当代大学生的日常学习和生活中&#xff0c;手机已经成为必不可少的工具&#xff0c;这导致大学学习生活中的各种日常生活及学习事务需要通过手机作为媒介进行通知及处理。而目前市场上存在的各种社交软件&#xff08;如QQ、微信等&#xff09;并不是为大学生量身定…

团队博客————学生成绩管理系统

项目简介&#xff1a; 支持实现教师端的登录注册&#xff0c;增添、修改与删除学生信息&#xff0c;增添学生时学号自动生成&#xff1b;将学生成绩导入并按照总分排序&#xff0c;查询成绩并支持模糊匹配&#xff1b;可导出学生成绩到excel表格&#xff1b;可生成以分数段划分…

基于android的学生选课信息app

学生选课系统是一个学校不可缺少的部分&#xff0c;该系统可以快速方便的使学生完成课程的选修及选修课程的管理&#xff0c;让管理员方便的管理选修课和设置选修时间&#xff0c;教师也可以查看自己代的选修课和给学生录入成绩。 本软件是一个Android 客户端JSP Servlet服务端…

安卓学生管理系统

安卓学生管理系统是大三时的期末作业&#xff0c;这里附上github链接&#xff0c;给需要交作业的小朋友~ app截图如下&#xff1a;

Android 学生管理系统

Android学生管理系统 由android mysql实现 1.需求分析 功能需求和页面需求两天没有细想&#xff0c;想到啥功能写啥功能想到啥界面写啥界面 2.系统设计 总体界面结构参照了微信的设计结构&#xff0c;主要功能包括管理员的注册和登录&#xff0c;所有学生信息的查询、单个…

奏响风电数字化“协奏曲”,联想助力世优电气打造智能管理闭环

双碳目标之下&#xff0c;可再生能源行业的快速增长&#xff0c;以及能源电力企业降本增效的需求&#xff0c;使得智能化管理平台成为新能源企业数字化转型的关键选择。 这一点&#xff0c;湖南世优电气股份有限公司&#xff08;以下简称“世优电气”&#xff09;感触颇深。作为…

探访世优科技数字人虚拟直播产品体系 | 世优开放日再次成功举行

2023年5月30日&#xff0c;世优科技全栈技术产品体验活动&#xff08;第二期&#xff09;顺利落下帷幕。此次活动共邀请到30余位各行各业的嘉宾到场&#xff0c;在两个多小时的开放日活动中&#xff0c;世优科技全面展示数字人及虚拟直播领域的技术产品体系。来访嘉宾们全程体验…

斩获5项大奖,世优科技虚拟人驱动技术亮相2022亚洲VRAR博览会

2022第6届以“开放共建创造融合”为主题的亚洲VR&AR博览会于8月12日落下帷幕。在数字经济发展和5G时代的大浪潮下&#xff0c;VR/AR产业链正在迎来加速发展&#xff0c;这从博览会的现场盛况可见一斑&#xff0c;本届展会吸引了众多来自海内外的VR/AR领域专家、学者&#x…

世优科技虚拟数字人直播方案,助力企业品牌破局直播同质化难题

随着互联网的快速发展&#xff0c;短视频带货、直播带货行业呈现出井喷式发展&#xff0c;网络电商直播已经成长为一个巨大的产业。预计2026年&#xff0c;我国网络直播市场规模将超过2万亿元。直播的快速发展越来越深刻地影响人们的消费及生活方式。但火热的同时&#xff0c;也…

元宇宙世界杯来袭,虚拟数字人+虚拟场景开创世界杯观赛全新体验

距离万众期盼的2022卡塔尔世界杯开幕已不足一周&#xff0c;世界杯作为全球最负盛名的体育赛事&#xff0c;不仅是球迷的节日&#xff0c;更是属于全民的狂欢。在开赛之际&#xff0c;中国移动重磅发布世界杯“元宇宙”全新玩法&#xff0c;通过融合“虚拟技术融合创新”全量全…

iDWF互博会即将开幕,世优科技携虚拟人女娲及虚拟直播SaaS平台亮相

助力数字经济发展的新引擎&#xff0c;探索“元宇宙”的新窗口&#xff0c;链接政产学研用金的新平台&#xff0c;全景数字生活的超级体验馆。以“通向数字新世界”为主题&#xff0c;2022互联网技术与应用博览会&#xff08;简称&#xff1a;iDWF互博会&#xff09;即将于2022…

AI数字人产品“世优BOTA”发布会 ,世优科技上海发起人刘凯源演讲回顾

4月20日&#xff0c;世优&#xff08;北京&#xff09;科技有限公司正式发布了新一代AI数字人产品——“世优BOTA”。世优科技上海发起人刘凯源表示&#xff0c;“数字人是元宇宙重要生产力&#xff0c;世优BOTA是人机交互的里程碑式作品”。世优BOTA可以帮助企业快速实现自有数…