Java基础 - 坦克大战(第三章,线程基础与线程使用)
文章目录
- 本章内容 - 多线程处理
- 绘制敌方坦克
- 线程基础
- 线程相关概念
- 程序(program)
- 进程
- 什么是线程
- 其他相关概念
- 单线程
- 多线程
- 并发
- 并行
- 获取当前电脑处理器(cpu)个数
- Java中创建线程的两种方式
- 线程基本使用(重要)
- 案例1
- 使用JConsole监控器
- 为什么使用start()方法(重点)
- 案例2
- 实现Runnable接口
- 设计模式(代理模式)
- 线程作业练习
- 继承Thread 和 实现Runnable的区别
- 案例演示
- 注意
本章内容 - 多线程处理
绘制敌方坦克
- 因为敌人的坦克,是在MyPanel上,所以我们的代码在MyPanel
- 因为敌人的坦克,后面有自己的特殊的属性和方法,可以单开一个EnemyTank
- 敌人坦克数量多,可以放入到集合Vector(多线程安全性)
- 新建EnemyTank类继承Tank类,构造方法传入x,y
public class EnemyTank extends Tank {public EnemyTank(int x, int y){super(x,y);}}
- 创建集合,遍历并初始化坦克位置
//定义我的坦克Hero hero = null;//定义敌人坦克,放入到Vector集合Vector<EnemyTank> enemyTanks = new Vector();int enemyTanksSize = 3;public MyPanel(){hero = new Hero(500,500); //初始化自己的坦克hero.setSpeed(50); //初始化坦克速度//初始化敌人坦克for (int i = 0; i < enemyTanksSize; i++) {enemyTanks.add(new EnemyTank(100 + i * 100,100));}}
- paint方法中,for循环画出敌方坦克
public void paint(Graphics g){super.paint(g);g.fillRect(0,0,1000,750); //填充矩形,默认黑色//画出坦克 - 封装方法//自己的坦克drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),1); //type坦克类型//敌人的坦克for (int i = 0; i < enemyTanks.size(); i++) {//取出坦克EnemyTank enemyTank = enemyTanks.get(i);drawTank(enemyTank.getX(),enemyTank.getY(),g,enemyTank.getDirect(),0);}}
- 地方坦克炮筒向下
for (int i = 0; i < enemyTanks.size(); i++) {//取出坦克EnemyTank enemyTank = enemyTanks.get(i);enemyTank.setDirect(2); //默认向下drawTank(enemyTank.getX(),enemyTank.getY(),g,enemyTank.getDirect(),0);}
线程基础
线程相关概念
程序(program)
是为完成特定任务、用某种语言编写的一组指令的集合。
简单的说:就是我们写的代码
进程
- 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间。
- 进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的产生,存在和消亡的过程
什么是线程
- 线程由进程创建的,是进程的一个实体
- 一个进程可以拥有多个线程,如下图(emm,大概就是这个意思叭~~)
其他相关概念
单线程
同一时刻,只允许执行一个线程
多线程
同一时刻,可以执行多个线程,比如:一个qq进程,可以同时打开多个聊天窗口,一个迅雷进程,可以同时下载多个文件
并发
同一个时刻,多个任务交替执行,造成一种“貌似同时”的错觉,简单的说,单核cpu实现的多任务就是并发
并行
同一个时刻,多个任务同时执行。多核cpu可以实现并行。
获取当前电脑处理器(cpu)个数
Runtime类
/*** Create By 刘鸿涛* 2022/1/14 2:51*/
public class CupNum {public static void main(String[] args) {Runtime runtime = Runtime.getRuntime();//Processors :处理器int cupNums = runtime.availableProcessors();System.out.println("我的电脑的cpu个数为:" + cupNums);}
}
Java中创建线程的两种方式
- 继承Thread类,重写run方法
- 实现Runnable接口,重写run方法
线程基本使用(重要)
案例1
- 编写程序,开启一个线程,该线程每隔1秒,在控制台输出“喵喵,我是小喵咪”
- 对上题改进:当输出80次“喵喵,我是小喵咪”,结束该线程
- 使用JConsole监控线程执行情况,并画出程序示意图
package com.tao.threaduse;/*** Create By 刘鸿涛* 2022/1/14 3:07*/
public class Thread01 {public static void main(String[] args) throws InterruptedException {Cat cat = new Cat();//启动线程cat.start(); //Thread类方法,实现Tunnable则无次方法//说明:当main线程启动一个子线程Thread-0,主线程不会阻塞,会继续执行System.out.println("主线程继续执行" + Thread.currentThread().getName()); //main线程for (int i = 0; i < 35; i++) {System.out.println("主线程" + i);if(i == 34){System.out.println("主线程已死");}//让主线程休眠Thread.sleep(1000);}}
}//1.当一个类继承了 Thread 类,该类就可以当作线程使用
//2.我们会重写 run 方法,写上自己的业务代码
//3.run Thread 类 实现了 Tunnable 接口的 run方法
class Cat extends Thread{ //implements Tunnable@Overridepublic void run() { //重写run方法int count = 0;while (true){try{Thread.sleep(1000); //程序休眠1000毫秒}catch(InterruptedException e){e.printStackTrace();}System.out.println("喵喵,我是小喵咪" + Thread.currentThread().getName()); //打印线程名字count++;if(count == 40){break;}}}
}
- 理论上可以更复杂些,比如下面这样
使用JConsole监控器
- 注意,需要程序运行时使用查找线程功能
为什么使用start()方法(重点)
因为你在main方法中调用run()方法后,你的线程名,依然是main,依然是单线程
start()方法调用start0()方法后,该线程并不一定会立马执行,只是将线程变成了可运行状态,具体什么时候执行,取决于CPU,由CPU统一调度
案例2
实现Runnable接口
- java是单继承的,在某些情况下一个类可能已经继承了某个父类,这时在用继承Thread类方法来创建线程显然不可能了
- java设计者们提供了另外一个方式创建线程,就是通过实现Runnable接口来创建线程
package com.tao.threaduse;/*** Create By 刘鸿涛* 2022/1/15 1:37*/
public class Thread02 {public static void main(String[] args) {Dog dog = new Dog();//Runnable接口没有start()方法
// dog.start();//实现思路//创建Thread对象,把 dog对象(实现Runnable),放入Thread类//这里用了设计模式中- 《代理模式》Thread thread = new Thread(dog);thread.start();}
}
class Dog implements Runnable{@Overridepublic void run() {int count = 0;while(true){System.out.println("小狗汪汪第" + (++count) + "次叫" + Thread.currentThread().getName());try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}if (count > 5){break;}}}
}
设计模式(代理模式)
- 我这个类没有这个方法,但是我可以请代理类帮我完成这个方法,但实际上工作的还是原来的类方法
package com.tao.threaduse;/*** Create By 刘鸿涛* 2022/1/15 1:53*/
public class Thread03 {public static void main(String[] args) {Tiger tiger = new Tiger(); //实现了Runnable接口Proxy proxy = new Proxy(tiger);//因为Tiger、Proxy都实现了Runnable接口proxy.start();}
}
class Animal{}
class Tiger extends Animal implements Runnable{@Overridepublic void run() {System.out.println("老虎嗷嗷叫..." + Thread.currentThread().getName()); //main线程}
}
//Proxy:代理
//线程代理类,模拟了一个极简的Thread类
class Proxy implements Runnable{ //你可以把Proxy类当作 Thread,private Runnable target = null; //属性,类型是 Runnable@Overridepublic void run() {if (target != null){target.run(); //动态绑定(运行类型Tiger)}}public Proxy(Runnable target){ //target = tigerthis.target = target;}public void start(){start0(); //这个方法真正实现多线程}public void start0(){run();}
}
线程作业练习
package com.tao.threaduse;/*** Create By 刘鸿涛* 2022/1/15 2:22*/
public class Homework01 {public static void main(String[] args) {Thread01_ thread01_ = new Thread01_();Thread thread = new Thread(thread01_);thread.start(); //线程1 - Thread-0Thread02_ thread02_ = new Thread02_();thread02_.start();}
}
class Thread01_ implements Runnable{@Overridepublic void run() {int count = 0;while(true){System.out.println("第" + ++count + "helloword" + Thread.currentThread().getName());try{Thread.sleep(1000);}catch(InterruptedException e){}if (count == 10){break;}}}
}
class Thread02_ extends Thread{@Overridepublic void run(){int count = 0;while(true){System.out.println("第" + ++count + "hi" + Thread.currentThread().getName());try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}if (count == 5){break;}}}
}
继承Thread 和 实现Runnable的区别
- 从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口
- 实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制
- 建议使用Runnable接口
案例演示
- [售票系统],编程模拟三个售票窗口售票100,分别使用 继承 Thread 和实现Runnable方式,并分析有什么问题?
package com.tao.threaduse;/*** Create By 刘鸿涛* 2022/1/15 4:45*/
public class Homework02 {public static void main(String[] args) {//继承Thread
// SellTicket01 sellTicket01 = new SellTicket01();
// SellTicket01 sellTicket02 = new SellTicket01();
// SellTicket01 sellTicket03 = new SellTicket01();
// sellTicket01.start(); //启动售票线程
// sellTicket02.start(); //启动售票线程
// sellTicket03.start(); //启动售票线程//实现Runnable接口
// SellTicket02 sellTicket02 = new SellTicket02();
// SellTicket02 sellTicket021 = new SellTicket02();
// SellTicket02 sellTicket022 = new SellTicket02();
// Thread thread = new Thread(sellTicket02);
// Thread thread1 = new Thread(sellTicket021);
// Thread thread2 = new Thread(sellTicket022);
// thread.start();
// thread1.start();
// thread2.start();SellTicket02 sellTicket02 = new SellTicket02();new Thread(sellTicket02).start();new Thread(sellTicket02).start();new Thread(sellTicket02).start();}
}
class SellTicket01 extends Thread{private static int ticketNum = 100; //@Overridepublic void run(){while(true){if(ticketNum <= 0){System.out.println("售票结束");break;}try{Thread.sleep(50);}catch(InterruptedException e){e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() +"卖出了一张票" + "\n剩余票数:" + (--ticketNum));}}
}
class SellTicket02 implements Runnable{private static int ticketNum = 100; //@Overridepublic void run(){while(true){if(ticketNum <= 0){System.out.println("售票结束");break;}try{Thread.sleep(50);}catch(InterruptedException e){e.printStackTrace();}System.out.println("窗口 " + Thread.currentThread().getName() +"卖出了一张票" + "\n剩余票数:" + (--ticketNum));}}
}
- 不管是继承Thread还是实现Runnable接口,都会出现超卖现象
注意
- main线程可以比其他线程先死!
Java基础 - 坦克大战(第三章,线程基础与线程使用)相关推荐
- JAVA之坦克大战(三)我方坦克发射炮弹
思路:添加子弹类,并且写出子弹运行的线,然后在Mytank中添加新的fire()方法,用于发射子弹时获得当前炮管的方向,因为子弹较多所以需要把子弹放在Vector集合里,并且需要开多线程,因为子弹运动 ...
- java坦克大战登录界面设计_基于JAVA的坦克大战设计和实现-代码.doc
JISHOU UNIVERSITY 本科生毕业设计 题 目:基于JAVA的坦克大战设计与实现作 者:学 号:所属学院:专业年级:指导教师:职 称:完成时间:2012年5月7日 吉首大学 基于JAVA的 ...
- Java版坦克大战游戏
技术:Java等 摘要: Java随着各种电子设备,其中尤其是移动通信设备的发展所诞生的一项新的开发技术.Java定位在各种电子设备产品的功能应用上,对电子产品的多样,智能化,提供了很大的帮助.本次设 ...
- 软考 程序员教程-第三章 数据库基础知识
软考 程序员教程-第三章 数据库基础知识 第三章 数据库基础知识 3.1 基本概念 数据库系统(DataBase System,DBS)由数据库(DataBase,DB).硬件.软件和人员4大部分组成 ...
- java小组坦克大战游戏开发文档开发日志_java实现坦克大战游戏
本文实例为大家分享了java实现坦克大战游戏的具体代码,供大家参考,具体内容如下 一.实现的功能 1.游戏玩法介绍 2.自定义游戏(选择游戏难度.关卡等) 3.自定义玩家姓名 4.数据的动态显示 二. ...
- Java实现坦克大战,单机版和联网版
Java实现坦克大战 源码获取途径 部分源代码 源码获取途径 百度网盘链接: 百度网盘地址 提取码:5r7i GitHub Github获取地址 部分源代码 public class TankClie ...
- 【JAVA程序设计】基于JAVA的坦克大战小游戏--入门级小游戏
基于JAVA的坦克大战小游戏--入门级小游戏 零.项目获取 一.项目简介 二.开发环境 三.游戏玩法 四.运行截图 零.项目获取 获取方式(点击下载):是云猿实战 项目经过多人测试运行,可以确保100 ...
- java怎么连发子弹_【Java_项目篇1】--JAVA实现坦克大战游戏--子弹连发+爆炸效果(四)...
前期相关文章 [Java_项目篇<1>]–JAVA实现坦克大战游戏–画出坦克(一) [Java_项目篇<1>]–JAVA实现坦克大战游戏–坦克移动+添加敌方坦克(二) [Jav ...
- 【Java_项目篇1】--JAVA实现坦克大战游戏--坦克移动+添加敌方坦克(二)
前期文章: [Java_项目篇<1>]--JAVA实现坦克大战游戏--画出坦克(一) 控制小球移动 1.外部类 实现KeyListener监听接口写法 package com.test3; ...
- 第三章网络安全基础考试要点及真题分布
第三章网络安全基础 1.计算机网络基本知识 2.网络安全的基本概念 3.网络安全威胁 4.网络安全防御 5.无线网络安全
最新文章
- ios签名软件_如何给无法上架App Store的App做ios签名?
- Nature:FB和推特的数据是如何革新社会科学,改变世界的?
- python怎么样才算入门编程-新手如何入门Python编程
- php 挂机,用php实现qq挂机
- HDU 2859 Phalanx (dp)
- JVM从入门到精通(九):JVM调优实战 - arthas 的使用
- oracle 误删表空间文件启动不了数据库的解决办法
- 每次请求刷新token的时间
- MTK 驱动(73)--- Kernel Backtrace 无法显示出具体的地址.
- hibernate之自定义持久化实现
- python 获取当前路径_Python获取当前路径实现代码
- 【语言学习】Java
- 输入姓名自动生成拼音
- Unity中录制VR全景视频(可录制UGUI)
- 天龙八部服务器维护几点开服,天龙八部开服时间表2020-开服时间表一览
- nginx完全卸载删除
- ORACLE一次大量数据删除导致问题的处理
- mac安装php的mongodb扩展报错:No such file or directory autom4te: /usr/bin/m4 failed with exit status: 1...
- ArcGIS教程:了解欧氏距离分析
- k8s学习(二十) helm的基本使用