黑马程序员技术交流社区
标题: 就业办7-10天的学习笔记 [打印本页]
作者: 社会人 时间: 2018-11-26 15:19
标题: 就业办7-10天的学习笔记
第七天
线程池通信等待唤醒机制等待唤醒机制: wait/notify, 就是"线程间的一种协作机制", 用于实现线程间通信
等待唤醒中的方法 java.lang.Object类: // 成员方法 (只能通过"锁对象"调用) 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个方法
线程池普通创建线程方式的缺点:
"创建"线程和"销毁"线程都是比较占用内存和CPU的操作. 对于一些数量多, 执行时间短的任务, 频繁的创建和销毁线程来执行, 会降低程序运行效率.
线程池:
一个容纳多个线程的容器(集合)
线程池可以解决的问题:
其中的线程可以反复使用, 省去了频繁创建线程对象的操作, 无需反复创建线程而消耗过多资源
线程池的工作原理:
提前创建好多个线程对象, 放在集合中. 多个任务来了反复使用这些线程对象来执行
public class RunnableImpl implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "号柜台为您服务");
System.out.println("顾客正在办理业务...");
try { Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "号柜台期待您再次光临");
System.out.println("--------------------------------------------");
}
}
public class Test {
public static void main(String[] args) { // 创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(2); // 提交10个任务
for (int i = 0; i < 10; i++) {
executorService.submit(new RunnableImpl());
} // 可以关闭也可以不关闭 executorService.shutdown();
}
}
函数式编程思想:Lambda表达式冗余的Runnable代码// 我们要通过Lambda表达式简化以下的代码
new Thread(new Runnable() {
@Override
public void run() { // 要执行的代码才是重要的 }
}).start();
关键代码是: run()方法中要执行的任务 而其他代码都只是形式
Lambda更优写法 // 函数式编程的代码 new Thread( ()-> { System.out.println(Thread.currentThread().getName() + "新线程创建了");
}
).start();
Lambda标准格式Lambda表达式的3个部分:
格式: // 写成多行 (数据类型 变量名, 数据类型 变量名) -> {
一些重写方法的代
}
可以合并为一行代码;
Lambda重写的有参有返回值的方法
Arrays.sort(arr, (Person o1, Person o2) -> {
return o1.getAge() - o2.getAge();
});
Lambda自定义接口,抽象方法有参有返回值
invokeCalc(120, 130, (int a, int b)->{
return a + b;
});
第八天
File类构造方法
public File(String pathname) :
通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
public File(String parent, String child) :
从父路径名字符串和子路径名字符串创建新的 File实例。
public File(File parent, String child) :
从父抽象路径名和子路径名字符串创建新的 File实例。
常用方法
public String getAbsolutePath() :
返回此File的绝对路径名字符串。
public String getPath() :
将此File转换为路径名字符串。
public String getName() :
返回由此File表示的文件或目录的名称。
public long length() :
返回由此File表示的文件的长度。
绝对路径和相对路径绝对路径:从盘符开始的路径,这是一个完整的路径。
相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。
判断功能的方法public boolean exists() :此File表示的文件或目录是否实际存在。
public boolean isDirectory() :此File表示的是否为目录。 public boolean isFile() :此File表示的是否为文件。
创建删除功能的方法public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
public boolean delete() :删除由此File表示的文件或目录。 public boolean mkdir() :创建由此File表示的目录。 public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
目录的遍历public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。
递归递归:指在当前方法内调用自己的这种现象。
递归的分类: 递归分为两种,直接递归和间接递归。 直接递归称为方法自身调用自己。 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
注意事项: 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。 构造方法,禁止递归
递归累加求和计算1到n的和
public class DiGuiDemo { public static void main(String[] args) { 使
int num = 5;
int sum = getSum(num);
System.out.println(sum);
}
public static int getSum(int num) {
if(num == 1){
return 1;
} return num + getSum(num‐1);
}
}
第九天
字节流根据数据的流向分为:输入流和输出流。输入流 :把数据从 其他设备 上读取到 内存 中的流。
输出流 :把数据从 内存 中写出到 其他设备 上的流。
格局数据的类型分为:字节流和字符流。字节流 :以字节为单位,读写数据的流。
字符流 :以字符为单位,读写数据的流。
字节输出流public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输 出到此输出流。 public abstract void write(int b) :将指定的字节输出流。
FileOutputStream类public FileOutputStream(File file) :创建文件输出流以写入由指定的 File对象表示的文件。 public FileOutputStream(String name) : 创建文件输出流以指定的名称写入文件。 当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文 件,会清空这个文件的数据。
1.写出字节: write(int b) 方法,每次可以写出一个字节数据
2.写出字节数组: write(byte[] b) ,每次可以写出数组中的数据
3.写出指定长度字节数组: write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节
数据追加续写ublic FileOutputStream(File file, boolean append) : 创建文件输出流以写入由指定的 File对象表示的 文件。 public FileOutputStream(String name, boolean append) : 创建文件输出流以指定的名称写入文件。 这两个构造方法,参数中都需要传入一个boolean类型的值, true 表示追加数据, false 表示清空原有数据。 这样创建的输出流对象,就可以指定是否追加续写了,
字节输入流InputStreampublic void close() :关闭此输入流并释放与此流相关联的任何系统资源。
public abstract int read() : 从输入流读取数据的下一个字节。 public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
FileInputStream类FileInputStream(File file) : 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系 统中的 File对象 file命名。
FileInputStream(String name) : 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件 系统中的路径名 name命名。
读取字节数据 字符流字符输入流Readerpublic void close() :关闭此流并释放与此流相关联的任何系统资源。
public int read() : 从输入流读取一个字符。 public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中
FileReader类FileReader(File file) : 创建一个新的 FileReader ,给定要读取的File对象。
FileReader(String fileName) : 创建一个新的 FileReader ,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。
读取字符数据 读取字符: read 方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回 -1 ,循环读 取
使用字符数组读取: read(char[] cbuf) ,每次读取b的长度个字符到数组中,返回读取到的有效字符个数, 读取到末尾时,返回 -1
字符输出流Writervoid write(int c) 写入单个字符。
void write(char[] cbuf) 写入字符数组。
abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len 写的字符个数。
void write(String str) 写入字符串。
void write(String str, int off, int len) 写入字符串的某一部分,off
字符串的开始索引,len写的字符个 数。
void flush() 刷新该流的缓冲。
void close() 关闭此流,但要先刷新它。
FileWriter类FileWriter(File file) : 创建一个新的 FileWriter,给定要读取的File对象。
FileWriter(String fileName) : 创建一个新的 FileWriter,给定要读取的文件的名称。 当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。
写出字符: write(int b) 方法,每次可以写出一个字符数据
关闭和刷新 flush :刷新缓冲区,流对象可以继续使用。
close :先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了
写出字符数组 : write(char[] cbuf) 和write(char[] cbuf, int off, int len) ,每次可以写出字符数 组中的数据,用法类似FileOutputStream
写出字符串: write(String str) 和write(String str, int off, int len) ,每次可以写出字符串中的 数据,更为方便
续写和换行:操作类似于FileOutputStream
属性集 Properties类构造:
public Properties() :创建一个空的属性列表
基本储存方法:
public Object setProperty(String key, String value) : 保存一对属性。 public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。 public Set<String> stringPropertyNames() :所有键的名称的集合。
第十天
缓冲流 缓冲字节输出流: BufferedOutputStream 字节缓冲流
|_ BufferedInputStream # 缓冲字节输入流 |_ BufferedOutputStream # 缓冲字节输出流
字符缓冲流
|_ BufferedReader # 缓冲字符输入流
|_ BufferedWriter # 缓冲字符输出流 java.io.BufferedOutputStream类: 缓冲字节输出流
// 构造方法
BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流 BufferedOutputStream(OutputStream out, int size): 使用基本流创建一个缓冲字节输出流, 设置 缓冲区大小 BufferedOutputStream使用步骤:
1.创建FileOutputStream对象, 构造方法中绑定要输出的目的地 2.创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象
3.使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区中
4.使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷新到文件中
5.释放资源(会先调用flush方法刷新数据, 第4步可以省略) FileOutputStream fos = new FileOutputStream("文件路径"); BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("你好".getBytes());
// bos.flush(); // 可以省略
bos.close();
缓冲字节输入流: BufferedInputStream java.io.BufferedInputStream类: 缓冲字节输入流
// 构造方法
BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流
BufferedInputStream(InputStream in, int size): 使用基本流创建一个缓冲字节输入流, 设置缓冲 区大小
使用步骤:
1.创建FileInputStream对象, 构造方法中绑定要读取的数据源
2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象
3.使用BufferedInputStream对象中的方法 read(), 读取文件
4.释放资源 close() FileInputStream fis = new FileInputStream("文件路径");
BufferedInputStream bis = new BufferedInputStream(fis); byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) { System.out.println(new String(bytes, 0, len));
}
bis.close();
缓冲流的效率测试: 复制文件 基本流 一次读写一个字节 一个字节
基本流 一次读写一个字节数组 一个字节数组
缓冲流 一次读写一个字节 一个字节数组
缓冲流 一次读写一个字节数组 两个字节数组
缓冲流 + 一次读写一个字节数组 效率最高
缓冲字符输出流: BufferedWriter // 构造方法 BufferedWriter(Writer out): 使用基本流创建一个缓冲字符输出流
BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小
// 特有方法
void newLine(): 写入一个换行符, 换行符自动根据当前系统确定
转换流 字符编码和字符集编码: 字符 -> 字节 'a' -> 97 解码: 字节 -> 字符 97 -> 'a'
编码表: 字符和二进制数字的对应规则
字符集和编码表: 字符集包含编码表
ASCII字符集
ASCII编码表
ASCII扩展编码表
ISO-8859-1字符集: Tomcat Web服务器程序
Latin-1: 拉丁字符. 没有中文. 每个字符由1个byte组成 GB字符集
GB2312编码表: 每个字符由2个byte组成
GBK编码表: 每个字符由2个byte组成
GB18030编码表: 每个字符由1, 2, 4个byte组成
Unicode字符集
UTF-8: ASCII字符占1个byte, 拉丁字符占2个byte, 中文占3个byte, Unicode辅助字符占4个byte
UTF-16
UTF-32
ANSI: 表示使用系统默认编码表
OutputStreamWriter类 OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流 OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流
// 使用默认UTF-8 OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt")); o.write("dsfdsfdsaf")
// 使用指定的GBK OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK"); osw.write("你") -> 查"GBK"码表 -> -1,-2 -> FileOutputStream -> a.txt文件
写数据: 字符流 --------------------------> 字节流
序列化流对象流对象序列化流: ObjectOutputStream // 构造方法
ObjectOutputStream(OutputStream out)
// 特有成员方法
void writeObject(Object obj): 将对象写出
// 创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student.txt"));
// 写对象
Student s = new Student("小美女", 18); oos.writeObject(s); // 释放资源
oos.close();
注意: 被读写的对象的类必须实现"java.io.Serializable"接口, 否则会抛出"NotSerializableException"
对象反序列化流: ObjectInputStream // 构造方法
ObjectInputStream(InputStream in)
// 特有成员方法
Object readObject(): 读取对象
// 创建对象输入流
ObjectInputStream oos = new ObjectInputStream(new FileInputStream("student.txt"));
// 读对象
Object o = oos.readObject(); Student s = (Student)o; System.out.println(s);
// 释放资源 oos.close();
今日API 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.io.OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁
// 构造方法
OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流 OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流
java.io.InputStreamReader类: 输入转换流. 字节流通往字符流的桥梁
// 构造方法
InputStreamReader(InputStream in): 使用默认编码表创建转换流
InputStreamReader(InputStream in, String charsetName): 使用指定编码表创建转换流
java.io.ObjectOutputStream类: 对象字节输出流
// 构造方法
ObjectOutputStream(OutputStream out)
// 特有成员方法
void writeObject(Object obj): 将对象写出 java.io.ObjectInputStream类: 对象字节输入流
// 构造方法
ObjectInputStream(InputStream in)
// 特有成员方法
Object readObject(): 读取对象
java.io.PrintStream类: 字节打印流 // 构造方法 PrintStream(File file): 创建字节打印流, 输出到一个文件 PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径 java.lang.System类:
// 静态方法
static void setOut(PrintStream out): 设置System.out的输出目的地为参数的打印流
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |