11_21
1.多线程的创建方式
多线程的创建方式2:
)自定义一个类实现Runnable接口
2)实现接口里面的run方法--->完成耗时操作
3)在main用户线程中创建当前这个类的实例--->"资源类对象"
4)创建线程类Thread对象,然后将3)资源类对象 作为参数传递,启动线程!
2.Java设计模式 结构型设计--->代理模式--->静态代理
代理设计模式
静态代理
动态代理
代理设计模式
代理核心思想: 真实角色专注自己的事情(开发中,针对自己的业务) 代理角色帮助真实完成一件事情 静态代理: 代理角色和真实角色要实现同一个接口
动态代理:后面讲
jdk动态代理 cglib动态代理(需要导入cglib.jar包)
3.解决线程安全
校验多线程安全问题的标准 (使用标准来看多线程环境是否存在问题,以及解决方案)
1)是否是多线程环境 --->是
2)是否有共享数据 ---> 是存在的
3)是否有多条语句对共享数据操作
tickets票:多条语句同时操作
将3)多条语句多共享数据的操作使用同步代码块包起来---解决线程安全问题
synchronized(锁对象){ * 多条语句对共享数据操作 * }
锁对象:可以是任意Java类对象,但是多个线程必须使用的同一个锁对象,否则"锁不住"!
什么是同步方法(非静态)?如果一个方法中第一句话是一个同步代码块,可以将synchronized关键字定义在声明上
权限修饰符 synchronized 返回值类型 方法名(参数列表){
...
}
锁对象:this---代表类对象的地址值引用 * 如果是静态的同步方法,锁对象---->当前类名.class(字节码文件对象)
4.为什么wait()和notify(),线程等待,线程唤醒为什么定义Object类中?
这些方法都是和锁对象有关系,而锁对象可以是任意Java类对象,而定义Object类中
调用 wait(),会立即释放锁!
11_22
1.jdk5以后Lock锁(接口)---->ReetrantLock可重入的互斥锁
Lock这个接口
Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作
实现类: 可重入的互斥锁 java.util.concurrent.locks.ReentrantLock
获取锁:指定的某个时刻 public void lock()
释放锁 : public void unlock() * Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock(); //释放锁(系统相关的资源)
}
电影院三个窗口同时出售100张票,使用方式2实现---->昨天使用synchronized同步代码块或则同步方法使用Lock进行锁定的操作:获取锁,以及释放锁
2.创建线程的方式3: 线程池
线程池:
会创建一些固定的可重复使用的线程数,会在线程池中,循环利用
当某些线程使用完毕,不会被释放掉,而是归还连接池中,等待下一次再去利用!
成本比普通创建线程方式要大!
java.util.concurrent.Exceutors 工厂类
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定的可重复的线程数的线程池
java.util.concurrent ExecutorService ----->接口的具体实现类 public class ThreadPoolExecutor
<T> Future<T> submit(Callable<T> task):提交异步任务,返回值就是异步任务计算的结果;
上面这个的返回值Future :异步计算的结果---如果现在只是看多个线程是否能够并发的去强转CPU执行权,并没有返回结果
这个返回值可以不用返回!
Callable:接口---->异步任务的执行 类似于 之前Runnable接口
void shutdown():关闭线程池
3.Java提供了 Timer定时器----执行定时任务TimerTask
java.util.Timer:定时器(可以执行一次或者重复执行某个任务)
构造方法:
Timer():创建一个计时器
成员方法
public void cancel()取消定时器
void schedule(TimerTask task, Date time) :在给定的日期时间来执行TimerTask定时任务 --->
String dataStr = "2022-11-22 18:00" ;//---->日期文本---->java.util.Date
(应用场景:引入使用io流的方式,在指定时间点上,删除指定带内容的目录里面的所有.java文件)
void schedule(TimerTask task, long delay) :在给定多少毫秒后(延迟时间)执行这个定时任务
public void schedule(TimerTask task,long delay,long period):在指定延迟时间(delay)执行任务, 然后每经过固定延迟时间(period)重复执行任务
schedule这些方法第一个参数都是定时任务:TimerTask是一个抽象类,
1)可以定义具体的子类继承自TimerTask
2)直接可以使用抽象类的匿名内部类
4.使用java.io.File来描述路径形式
File(File parent, String child)
File(String pathname) 推荐第二个
File(String parent, String child)
5.IO流
基本功能:
创建文件/文件夹
public boolean createNewFile()throws IOException:创建文件,如果不存在,创建,返回true
public boolean mkdir():创建文件夹,如果存在了,则返回false;否则true
public boolean mkdirs():创建多级目录,当父目录不存在的时候创建
判断
public boolean isFile():是否是文件 使用居多
public boolean isDirectory():是否是文件夹 使用居多
public boolean isAbsolute():是否为绝对路径
public boolean exists():判断文件或者目录是否存在
删除
public boolean delete():删除由此抽象路径名表示的文件或目录 (删除目录,目录必须为空)
11_23
1.java.io.File ----> 高级功能:获取指定目录下的所有的文件夹以及文件的Fiie数组
java.io.File:高级功能
public File[] listFiles():获取指定抽象路径表示下的所有的File数组
推荐---->使用File的功能进行判断
public String[] list():抽象路径名表示的目录中的文件和目录。
2.递归算法
递归: 方法调用本身的一种现象! 不是方法嵌套方法
方法递归:
1)需要有方法
2)有一定规律
3)有方法结束的条件(出口条件),否则 "死递归"
构造方法没有递归
3.IO流的分类 (输入流和输出流)
1)按流的方向划分
输入流 ---->读
输出流 ---->写
2)按流的类型划分--同时按方向划分:
字节流
字节输入流:InputStream--->不能实例化--->具体的子类:针对文件的字节输入流 FileInputStream
字节输出流:OutputStream--->不能实例化--->具体的子类:针对文件的字节输出流 FileOutputStream 字节缓冲流(字节高效流)
字节缓冲输入流:BufferedInputStream
字节缓冲输出流:BufferedInputStream
字符流
字符输入流
字符输出流
4.基本字节流
public FileOutputStream(String name,boolean append) throws FileNotFoundException
创建字节文件输出流对象,实现文件的末尾追加,而不将之前覆盖,第二个参数必须为true
IO流操作的时候,加入异常处理代码格式---->开发中 try...catch...finally 使用捕获一次
字节输入流:InputStream--->读 抽象类
提供子类:FileInputStream:针对文件操作的字节输入流
1)创建文件字节输入流对象
2)读文件
public int read() throws IOException:一次读取一个字节,返回字节数
public int read(byte[] b) throws IOException:一次读取一个字节数组
3)释放资源
11_24
1.BufferedInputStream/BufferedOutputStream:字节缓冲流
字节缓冲输出流/输入流 (高效字节流)
BuffedOutputStream/BufferedInputStream:只是提供一个字节缓冲区,本身就是一个字节数组,不会直接操作文件
操作具体的文件使用都是基本字节流FileInputStream/FileOutputStream
public BufferedOutputStream(OutputStream out):创建一个字节缓冲输出流对象,默认缓冲区大小(足够大)
public BufferedInputStream(InputStream in):创建一个字节缓冲输入流对象,默认缓冲大小
2.字符流 (针对字符操作)
字符流是在字节流后出现,如果是文本文本进行操作,优先使用字符流!
字符流
Writer:具体的子类
public OutputStreamWriter(OutputStream out):
字符转换输出流(可以将基本字节输出流转换成字符输出流),平台默认的字符集编码(idea,utf-8)
public OutputStreamWriter(OutputStream out,String charsetName):
字符转换输出流 ,指定一个编码字符集
写的功能
void write(char[] cbuf)写入一个字符数组。
abstract void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写一个字符
void write(String str)写一个字符串
void write(String str, int off, int len) :写入字符串的一部分
Reader:抽象类
具体子类
public InputStreamReader(InputStream in):创建字符转换输入流,以平台默认字符集解码
public InputStreamReader(InputStream in,String charsetName):
创建字符转换输入流对象,指定字符集解码
read的功能 * public int read(char[] cbuf):读取字符数组
public int read():读一个字符
InputStreamReader/OutputStreamWriter:字符转换流弊端:代码格式复杂,不能直接操作文件!
3.字符缓冲流(使用居多) + 集合 + 多线程 (综合使用)
BufferedReader(Reader in):字符缓冲输入流
也可以键盘录入
main()里面String[] 可以键盘录入 ,录入字符串
Scanner以及提供的nextXXX()
BufferedReader:字符缓冲输入流
BufferedWriter:字符缓冲输出流
他们不能直接操作文件,提供缓冲区让读写效率更高,特有方式
BufferedReader一次读取一行/可以作为键盘录入(录入一行字符串内容)
字符流针对文本文件(记事本打开能看懂的)-->字符流读写复制
1)字符转换流InputStreamReader/OutputStreamWriter 一次读取一个字符/一次读取一个字符数组
2)使用字符转换流的便捷类FileReader/FileWriter 可以直击操作文件 一次读取一个字符/一次读取一个字符数组
3)使用字符缓冲流BufferedReader/BufferedWriter: 一次读取一个字符/一次读取一个字符数组
4)使用字符缓冲流BufferedReader/BufferedWriter :一次读取一行特有方式(推荐!)读写复制
4.序列化ObjectOutputStream/反序列化ObjectInputStream
序列化:将一个Java对象(当前的类以及属性--->签名信息)--->"流数据" 前提条件就是 当前对象的所在类型必须实现java.io.serializable序列化接口---->实现了这个接口的类才能被序列化,产生固定serialVersionUID唯一的标识ID
序列化:ObjectOutputStream---->将java对象--->写到序列化流中
public ObjectOutputStream(OutputStream out)
反序列化:ObjectInputStream---->将序列化中流数据的信息---->还原成Java对象
11_25
1.java.util.Properties(很重要):属性列表集合类
Properties类表示一组持久的属性。
Properties可以保存到流中或从流中加载。(重要的地方)
属性列表中的每个键及其对应的值都是一个字符串。
继承Hashtable---->实现Map接口---->存储数据,取出数据----都可以使用Map的方式
构造方法:
public Properties():创建空的属性列表
java.util.Properites属性列表有自己的遍历方式---底层基于Map实现的
添加元素:
public Object setProperty(String key, String value)
遍历属性列表
public Set<String> stringPropertyNames()获取属性列表中的所有的键
public String getProperty(String key)使用此属性列表中指定的键搜索属性
Properties特有方式
public void load(Reader reader)throws IOException :
将指定文件中的内容加载属性集合列表中(内容键值对 key=value)
void store(Writer writer, String comments) :将属性列表中的内容保存指定文件中(以"键=值"元素对进行保存)
第一个参数:字符输出/使用字节输出流
第二个参数:属性列表的描述
相当于:
打游戏---->进度的加载
关卡的保存
2. 网络编程---(最终区别:TCP和UDP)
java.net.InetAddress:代表互联网ip地址对象
想获取计算机的主机名称或者获取计算机的ip地址字符串形式?
public static InetAddress getByName(String host) throws UnknownHostException
通过计算机主机名称或者是字符串形式的ip地址--->获取互联网ip地址对象
UDP接收端的代码实现
1)创建接收端的Socket对象,绑定端口
2)创建一个接收容器--->数据包--->自定义字节缓冲区,将发送的数据包
3)接收
4)从接收容器中解析数据包的实际内容数据
5)展示数据
Upd方式--->不需要建立连接通道,不可靠连接
Udp发送端的步骤
1)创建发送端的socket
2)创建数据报包
3)使用发送端的Socket将数据存储数据包中, 发送(本质存储数据包)
4)释放资源
先运行接收端,而且接收端不能运行多次,否则端口被占用!