韩顺平java基础——坦克大战(含有线程、I\O流的讲解)
写在最前边:
研究生一枚,为后端实习和未来工作打基础。无意间发现韩顺平老师的课程,细心细致,讲课和吴恩达老师一样,都是保姆式讲解,各种基础知识都会补充,爱了。
韩顺平老师课程地址:https://www.bilibili.com/video/BV1fh411y7R8?spm_id_from=333.999.0.0
阅读提醒:本笔试适合有编程语言基础的伙伴阅读,因为本兔兔是本专业的,有c、c++、python 、sql基础,笔记中特别的基础的内容就没有记录。完全零基础的小伙伴建议跟着韩老师的课程自己记录。
============================= ❀ 坦 克 大 战 ❀ =============================
============================== ❀ 1.0 版 本 ❀ ==============================
用到泛型及其之前的知识
一、Java绘图坐标体系
1、像素——密度单位(
与厘米这种长度单位完全不是一回事
)与分辨率有关:分辨率越高像素越大,密度越高,展示的东西越丰富。
像素 = 分辨率的长× 宽
2、坐标介绍
二、Java绘图入门
1、步骤
定义一个类MyPanel extends JPanel,作为画板;
MyPanel 类中重写paint方法,使用Graphics类 作为画笔。进行一系列方法绘图;
定义一个类 DrawCircle extends JFrame ,作为活动窗口展示画板内容
DrawCircle 类中 声明一个画板类 MyPanel
在DrawCircle 类的构造器或者其他方法中创建MyPanel 对象并加入当前DrawCircle 类对象中
设置窗口大小以及是否显示
代码实例
import javax.swing.*; import java.awt.*; public class MyPanel extends JPanel{ @Override public void paint(Graphics g) { super.paint(g); g.drawOval(0,0,50,50); } } public class DrawCircle extends JFrame { private MyPanel mp = null; public static void main(String[] args) { new DrawCircle(); } public DrawCircle(){ mp = new MyPanel(); this.add(mp); this.setSize(200,200); this.setVisible(true); } }
2、重要类的方法
3、paint方法何时被调用
4、Graphics类(画笔)的绘图方法
5、Java事件处理机制——以键盘控制小球移动为例
此时,通过之前知识的运用,我们可以画出很多坦克,并且控制自己坦克的移动。还需要在2.0版本实现敌人坦克的自动移动呀↓
============================== ❀ 2.0 版 本 ❀ ==============================
加入多线程基础知识
补充:
IDEA中的 jconsole可视化线程工具
1、一些概念
····· 例如:迅雷应用代码
·······例如:迅雷应用
······例如:迅雷应用中的下载任务
······都是执行多任务的前提:
······单核CPU 是并发——通过交替执行使得用户认为在同时执行
······多核CPU 是并发——真正的同时执行
······当电脑执行任务个数超过CPU个数,则并发和并行在电脑中都存在
······Java查看电脑CPU的个数
2、线程分类
3、Java创建线程的方法本质都是使用Start0()
class Cat extends Thread{ run(){....} } public class Thread01{ //main方法就是 主线程 public static void main(String[] args) throw InterruptedException{ //Cat对象就是一个线程 Cat cat = new Cat(); cat.start(); //主线程不会被阻塞 for(int i = 0 ; i < 10 ;i++){ ... } }
记住1:进程结束的标志 不是主线程main结束,要看所有线程是否结束。
记住2:线程 也可以开辟 另一个线程
为什么在main使用start()方法启动线程而不是run()呢?
run()是一个普通方法,没有启动线程,并且会阻塞程序直到run执行完毕程序再继续执行 。
start()源码:
方法二:实现Runnable接口,重写run()方法为自己的业务逻辑,然后该类就可以看为一个线程(
底层使用了代理模式)
韩老师讲解视频地址对单继承机制的补充,使得某类继承了其他类的情况还可以使用多线程。同时适用于多个线程共享一个资源的情况。
线程类中的声明同上。但是创建线程不能直接使用start类,而是封装到Thread中才可以使用start()。
>public class Thread02{ //main方法就是 主线程 public static void main(String[] args) throw InterruptedException{ //Cat对象就是一个线程 Cat cat = new Cat(); //cat.start(); 不能使用了 Thread thread = new Thread(cat); thread .start(); //主线程不会被阻塞 for(int i = 0 ; i < 10 ;i++){ ... } }
4、线程终止
5、线程常用方法1
优先级:
interrupt()方法,一般用于中断(唤醒)正在休眠的线程。会抛给正在休眠的线程一个异常,那么在catch中我们就可以写上自己的 中断休眠后的业务逻辑代码。这也是为什么sleep()方法必须用try-catch的原因
6、线程常用方法2
7、线程常用方法3
8、线程7大状态
``java中的 Thread.State枚举了六种状态,但是RUNNABLE状态还可以细分为两个内核状态。
9、线程同步机制 Synchronized
``首先注意,锁的对象应该是同一个呀。如果我们new 了好几个那么底层就不是一个对象了,线程之间也没有争抢了。
使用Synchronized的2种方法
注意:run()方法不要写成Synchronized的呀
10、互斥锁
锁实际是在对象/.class上,而不是代码块上
synchronized (this)是非公平锁
细节5
细节6
11、死锁
12、释放锁
释放锁的4种时机
不会 释放锁的2种情况
============================== ❀ 3.0 版 本 ❀ ==============================
加入I/O流知识
1、一些概念
流不生产数据,只是文件数据的搬运工
2、常用文件操作 File类的使用
3、IO流原理
每创建一个IO流类的对象,其实就是分配了一个外卖小哥来送货(文件数据),至于到底一个文件中的数据怎么全部运输完(输入内存/输出到外部),根据每个外卖小哥自己的方法来决定,并且外卖小哥运输完成这一单后,应该被释放,以便可以继续接活
4、IO流分类
按操作数据的单位长度划分:
1)字节流(8bit)
好处:效率较低,适用于二进制文件,保证对二进制文件(如音频、视频、doc、pdf)的无损操作
2)字符流(=多少字节?根据
文件编码
来看)好处:效率较高,适用于文本文件
按数据流的流向划分:
1)输入流
2)输出流
以上四种可以两两组合成为四种 【抽象类】成为IO流中其他类的抽象基类,也就是说其他IO流类都是这四种抽象类的子类:
![]()
细节:字符流FileWriter进行写操作时,必须 close或者flush一下(刷新一下,否则还没有写入指定文件)
5、节点流和处理流
1)节点流 :
初级的外卖员,只能配送一种货物
从特定的数据源读写数据 。如FileReader 、 FileWriter、FileInputStream、FileOutputStream等
缺点:直接对数据源进行操作,不够灵活
2)处理流(包装流):
高级的外卖员,能配送多种货物
连接在 已存在的
节点流或处理流
上,提供更强大的读写功能。如:BufferedReader、BufferedWriter
优点1:处理流内部封装一个Reader/Writer/InputStream/OutputStream属性,即封装了一个节点流。那么使用的可以是任何的四大抽象基类的子类:
优点2:进行功能扩展
优点3、4
韩老师讲解视频地址
处理流的设计模式——修饰器模式:
6、配置文件的读写操作
配置文件不用IO流读写,而是使用专门的类Properties类: