day7【线程池、Lambda表达式】
等待唤醒机制介绍// 成员方法 (只能通过"锁对象"调用)
void notify(): 随机唤醒在同一个锁对象上的某一个处于等待状态的线程
void notifyAll(): 唤醒所有在同一个锁对象上处于等待状态的线程
void wait(): 让当前线程处于无限等待状态, 同时释放锁
wait和notify/notifyAll的执行原理:
wait:
线程不再活动, 不再参与调度, 进入 wait set 中, 因此不会浪费 CPU 资源, 也不会去竞争锁, 这时的线程状态即是"WAITING". 它还要等着别的线程执行"通知(notify)", 让在锁对象上等待的线程从 wait set 中释放出来, 重新进入到调度队列(ready queue)中
notify/notifyAll:
哪怕只通知了一个等待的线程, 被通知线程也不能立即恢复执行, 因为它当初中断的地方是在同步块内, 而
此刻它已经不持有锁, 所以它需要"再次尝试去获取锁"(很可能面临其它线程的竞争), 成功后才能在当初调用 wait() 之后的地方恢复执行
总结如下:
如果能获取锁, 线程就从"WAITING"状态变成"RUNNABLE"状态
否则, 从 wait set 出来, 又进入entry set, 线程就从"WAITING"状态又变成"BLOCKED"状态
调用 wait() 和 notify() 需要注意的细节:
1. wait() 与 notify() 必须要由"同一个锁对象"调用
因为对应的锁对象可以通过 notify() 唤醒使用同一个锁对象调用的 wait() 后的线程
2. wait() 与 notify() 是属于Object类的方法
因为锁对象可以是任意对象, 而任意对象的所属类都是继承了Object类的
3. wait() 与 notify() 必须要在"同步代码块"或者是"同步方法"中使用
因为必须要通过锁对象调用这2个方法
线程池概念和原理
*线程池:**其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。 Java里面线程池的顶级接口是java.util.concurrent.Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是java.util.concurrent.ExecutorService。
要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在java.util.concurrent.Executors线程工厂类里面提供了一些静态工厂,生成一些常用的线程池。官方建议使用Executors工程类来创建线程池对象。
Executors类中有个创建线程池的方法如下:
- public static ExecutorService newFixedThreadPool(int nThreads):返回线程池对象。(创建的是有界线程池,也就是池中的线程个数可以指定最大数量)
获取到了一个线程池ExecutorService 对象,那么怎么使用呢,在这里定义了一个使用线程池对象的方法如下:
- public Future<?> submit(Runnable task):获取线程池中的某一个线程对象,并执行
Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用。
使用线程池中线程对象的步骤:
- 创建线程池对象。 (使用线程池的工厂类Executors的静态方法newFixedThreadPool()新建一个线程池对象)
- 创建Runnable接口子类对象。(任务对象)(task)
- 提交Runnable接口子类对象。submit(take task)
- 关闭线程池(一般不做)。shutdown()
函数式编程思想-lamda表达式函数式:
在数学中, 函数就是有输入量, 输出量的一套计算方案, 也就是"传入什么东西, 得到什么结果"
y = f(x)
面向对象: 强调"用哪个对象的哪个方法"来做事 (注重语法形式: 继承 方法重写)
函数式: 强调"传入的参数 和 要执行的代码"
函数式编程的好处:
简化代码编写 (使用 λ Lambda表达式, 简化匿名内部类的代码)
[Java] 纯文本查看 复制代码 JDK 8 中, 加入的Lambda表达式, 是函数式编程思想中的重点
对比:
// 面向对象方式的代码
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "新线程创建了");
}
}).start();
// 函数式编程的代码
new Thread( ()-> {
System.out.println(Thread.currentThread().getName() + "新线程创建了");
}
).start();
Lamda标准格式
格式:
[Java] 纯文本查看 复制代码 格式:
// 写成多行
(数据类型 变量名, 数据类型 变量名) -> {
一些重写方法的代码
一些重写方法的代码
...
}
// 如果代码只有一行, 也可以合并写成一行
(参数列表) -> {一些重写方法的代码}
day8【File类、递归】
File类概述[Java] 纯文本查看 复制代码 Windows系统是 分号;
Linux系统是 冒号:
static String separator: 文件名称分隔符的字符串形式
static char separatorChar: 文件名称分隔符的char形式
Window系统是 反斜杠\
Linux系统是 正斜杠/
// 构造方法(创建了File对象, 并将其指向该路径. 不会真正在磁盘上创建这个文件)
File File(String pathname): 根据 路径字符串 封装一个File对象
File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
// 常用获取方法
String?getAbsolutePath(): 返回此File的绝对路径名字符串
String?getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String?getName(): 获取File对象的文件名或目录名
long?length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
// 常用判断方法
boolean?exists(): 判断File对象代表的文件或目录是否实际存在
boolean?isDirectory(): 判断File表示的是否为目录
boolean?isFile(): 判断File表示的是否为文件
// 常用创建删除方法
boolean?createNewFile(): 当文件不存在时, 创建一个新的空文件
boolean?delete(): 删除由此File表示的文件或目录. (删除目录时必须是空目录)
boolean?mkdir(): 创建File表示的目录
boolean?mkdirs(): 创建File表示的多级目录
// 常用获取目录中内容的方法
String[]?list(): 获取当前File目录下的所有子文件或目录的名字数组
File[]?listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组
File[] listFiles(FileFilter filter): 通过File对象过滤, 返回文件过滤器过滤后的File对象数组
File[] listFiles(FilenameFilter filter): 通过File对象的文件名过滤, 返回文件过滤器过滤后的File对象数组
递归递归思想:
遇到一个问题时, 将该问题拆解成可以解决的小问题, 如果解决不了, 继续拆解为更小的问题. 如果小问题解决了, 大问题也就能够解决
Java中实现递归的方式:
方法内部调用方法自己 (所以必须定义方法)
递归的分类:
直接递归: 方法自己调用方法
间接递归: A方法调用B方法, B方法调用C方法, C方法调用A方法
递归时的注意事项:
1. 递归要有限定条件(出口), 保证递归能够停止(就是在某种情况下方法不再调用自己), 否则会栈内存溢出
2. 递归次数不能太多, 否则会栈内存溢出
3. 构造方法不能递归
递归的使用前提:
调用方法时, 方法的主体不变, 但每次传递的参数值不同, 可以使用递归
day9【字节流、字符流、Properties双列集合】
IO流的概念和分类
IO流: 输入(Input)输出(Output)流
流: 数据流
输入: 从硬盘(文件)读取到内存(Java程序)
输出: 从内存(Java程序)写入到硬盘(文件)
(入和出都是相对于内存来说的)
+---------+
输入 | | 输出
--------> | 内存 | -------->
| |
+---------+
IO流的分类:
字节流 (读写字节: byte, 可以读写所有类型的文件, 包括视频, 图片, 音频, 文本等)
字节输入流: java.io.InputStream 抽象类
字节输出流: java.io.OutputStream 抽象类
字符流 (读写字符: char, String, 只能读写文本文件)
字符输入流: java.io.Reader 抽象类
字符输出流: java.io.Writer 抽象类
[Java] 纯文本查看 复制代码 java.io.OutputStream抽象类: 字节输出流 (顶层类)
// 成员方法
void close() :释放资源
void?flush() :刷新缓冲区(对于字节流来说没有作用)
// 写字节的成员方法
abstract void?write(int?b): 一次写一个字节 (参数是int是为了代码中写表示byte的整数方便不用强转)
void?write(byte[]?b): 一次写一个字节数组
void?write(byte[]?b,?int?off,?int?len): 一次写一个字节数组的一部分
java.io.FileOutputStream类: 文件字节输出流 (向文件写数据)
// 构造方法
FileOutputStream(String?name): 通过文件路径创建文件字节输出流
FileOutputStream(File?file): 通过File对象创建文件字节输出流
FileOutputStream(String?name, boolean append): 通过文件路径创建文件字节输出流, true可以续写
FileOutputStream(File?file, boolean append): 通过File对象创建文件字节输出流, true可以续写
[b][size=4]字符字节输入输出流介绍[/size][/b]
java.io.InputStream抽象类: 字节输入流 (顶层类)
// 常用成员方法
void?close(): 释放资源
// 读数据的方法
int?read(): 一次读一个字节. 读到文件末尾返回-1 (返回int也是为了代码编写方便)
int?read(byte[]?b): 一次读一个字节数组. 读到的字节存放在参数中的字节数组中, 返回int值是本次读到的字节的个数. 读到文件末尾返回-1
java.io.FileInputStream类: 文件字节输入流
// 构造方法
FileInputStream(String?name): 使用文件路径创建文件字节输入流
FileInputStream(File?file): 使用File对象创建文件字节输入流
java.io.Reader抽象类: 字符输入流 (顶层)
// 常用成员方法
void?close() :关闭此流并释放与此流相关联的任何系统资源
// 读数据的方法
int?read(): 一次读一个字符char, 返回读到的字符. 读到文件末尾返回-1 (返回int为了代码编写方便)
int?read(char[]?cbuf): 一次读取一个字符数组char[]. 返回读取的字符个数. 读到文件末尾返回-1
java.io.FileReader类: 文件字符输入流
// 构造方法
FileReader(File?file): 根据File对象创建文件字符输入流
FileReader(String?fileName): 根据File对象创建文件字符输入流
java.io.Writer抽象类: 字符输出流 (顶层类)
// 常用成员方法
abstract void?close(): 刷新缓冲区并释放资源
abstract void?flush() :刷新缓冲区
// 写
void?write(int?c): 写一个字符 (int类型为了代码编写方便)
void?write(char[]?cbuf): 写一个字符数组
abstract void?write(char[]?b,?int?off,?int?len): 写一个字符数组的一部分
void?write(String?str): 写一个字符串
void write(String str, int off, int len): 写一个字符串的一部分
java.io.FileWriter类: 文件字符输出流
// 构造方法
FileWriter(File?file): 通过File对象创建文件字符输出流
FileWriter(String?fileName): 通过文件路径创建文件字符输出流
FileWriter(File?file, boolean append): 通过File对象创建文件字符输出流. 第二个参数为true可以续写
FileWriter(String?fileName, boolean append): 通过文件路径创建文件字符输出流. 第二个参数为true可以续写
properties双列集合
[Java] 纯文本查看 复制代码 java.util.Properties类: 属性集, 属于Map的双列集合, 继承自Hashtable
// 构造方法
Properties(): 创建一个Properties集合
// 可以使用Map接口中的方法
// 特有成员方法
Object?setProperty(String?key,?String?value): 保存/替换键值对
String?getProperty(String?key): 通过键获取值. 键不存在返回null
Set<String> stringPropertyNames(): 返回键的集合
void store(OutputStream out, String comments): 将集合数据用字节流写入文件(不能中文), 并写入注释
void store(Writer writer, String comments): 将集合数据用字符流写入文件(可以中文), 并写入注释
void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)
day10【缓冲流、转换流、序列化流、打印流】
缓冲流的使用
[Java] 纯文本查看 复制代码 java.io.BufferedOutputStream类: 缓冲字节输出流
// 构造方法
BufferedOutputStream(OutputStream?out): 使用基本流创建一个缓冲字节输出流
BufferedOutputStream(OutputStream?out, int size): 使用基本流创建一个缓冲字节输出流, 设置缓冲区大小
java.io.BufferedInputStream类: 缓冲字节输入流
// 构造方法
BufferedInputStream(InputStream?in): 使用基本流创建一个缓冲字节输入流
BufferedInputStream(InputStream?in, int size): 使用基本流创建一个缓冲字节输入流, 设置缓冲区大小
java.io.BufferedWriter类:
// 构造方法
BufferedWriter(Writer?out): 使用基本流创建一个缓冲字符输出流
BufferedWriter(Writer?out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小
// 特有方法
void?newLine(): 写入一个换行符, 换行符自动根据当前系统确定
java.io.BufferedReader类: 缓冲字符输入流
// 构造方法
BufferedReader(Reader?in): 使用基本流创建一个缓冲字符输入流
BufferedReader(Reader?in, int size): 使用基本流创建一个缓冲字符输入流, 设置缓冲区大小
// 特有方法
String?readLine(): 一次读一行字符串, "不包含换行符".
读到文件末尾返回 null
转换流的使用
[Java] 纯文本查看 复制代码 java.io.OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁
// 构造方法
OutputStreamWriter(OutputStream?out): 使用默认编码表创建转换流
OutputStreamWriter(OutputStream?out,?String?charsetName): 使用指定编码表创建转换流
java.io.InputStreamReader类: 输入转换流. 字节流通往字符流的桥梁
// 构造方法
InputStreamReader(InputStream?in): 使用默认编码表创建转换流
InputStreamReader(InputStream?in,?String?charsetName): 使用指定编码表创建转换流
序列化流的使用
[Java] 纯文本查看 复制代码 java.io.ObjectOutputStream类: 对象字节输出流
// 构造方法
ObjectOutputStream(OutputStream?out)
// 特有成员方法
void?writeObject(Object?obj): 将对象写出
java.io.ObjectInputStream类: 对象字节输入流
// 构造方法
ObjectInputStream(InputStream?in)
// 特有成员方法
Object?readObject(): 读取对象
字节打印流的使用
[Java] 纯文本查看 复制代码 java.io.PrintStream类: 字节打印流
// 构造方法
PrintStream(File file): 创建字节打印流, 输出到一个文件
PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
PrintStream(String?fileName): 创建字节打印流, 输出到一个文件路径
扩展:
java.lang.System类:
// 静态方法(System类中的)
static void setOut(PrintStream out): 设置System.out的输出目的地为参数的打印流
|
|