本帖最后由 13333114253 于 2018-12-3 09:31 编辑
01-线程间通讯
等待唤醒机制介绍:
等待唤醒机制: 一个线程进行了规定操作后,就进入等待状态( wait() ),等待其他线程执行完他们的制定代码过后再将其唤醒 ( notify() );
再有多个线程进行等待时,如果需要可以使用 notifyAll() 来唤醒所有的等待线程
等待唤醒中的方法:
成员方法只能通过"锁对象"调用
void notify() ;//随机唤醒在同一个锁对象上的某一处等待状态的线程
void notifyAll(); //唤醒同一锁上处于等待的线程
void wait(); //线程处于无线等待状态,同时释放锁资源
调用wait()和notify() 需要注意的细节:
1.wait()和notify()必须通过由"同一个锁对象"调用
2.wait()和notify()属于Object类的方法 锁对象可以是任意对象,都继承于Object类
3.wait()和notify()必须要在"同步带码块"或者是"同步方法"中使用
02-线程池
线程池:
一个容纳多个线程的容器 其中的线程可以反复使用,省去频繁创建线程对象的操作,无需反复创建线程而浪费资源
线程池代码的实现
java.util.concurrent.Executors类: 线程池工厂类, 用于管理线程池
// 静态方法:
static ExecutorService newFixedThreadPool(int nThreads): 创建固定数量线程的线程池(常用)
一哥载Q特儿 色儿微斯
java.util.concurrent.ExecutorService接口: 真正执行任务的线程池服务
// 成员方法:
Future submit(Runnable task): 提交一个Runnable任务
void shutdown(): 通知线程执行完任务后关闭. 如不调此方法, 则线程执行完任务后仍在运行以便重复使用
线程池的创建和使用步骤:
1. 使用Executors的静态方法 newFixedThreadPool(int nThreads) 创建线程池ExecutorService
2. 创建一个任务类, 实现Runnable接口, 重写run()方法
3. 调用ExecutorService对象的 submit(Runnable task) 方法, 传递任务给线程池, 执行任务
4. 调用ExecutorService对象的 shutdown() 方法, 销毁线程池 (不建议执行)
例:
模拟饭店服务员
饭店有2个服务员, 有2个桌子, 来了10个顾客, 同一时间只能有2个顾客入座用餐, 其余顾客要等待
[Java] 纯文本查看 复制代码 public class RunnableImpl implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"服务员开始为顾客点菜");
System.out.println("顾客"+this.hashCode()+"开始用餐");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("顾客"+this.hashCode()+"用餐完毕");
System.out.println(Thread.currentThread().getName()+"服务员收拾桌子");
System.out.println("-------------------------------");
}
}
public class Test {
public static void main(String[] args) {
// 创建线程池, 有2个线程, 模拟2个桌子
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 循环10次模拟10个顾客来用餐
for (int i = 0; i < 10; i++) {
executorService.submit(new RunnableImpl());
}
// 都执行完后关闭线程池
executorService.shutdown();
}
}
03-函数式编程思想:Lambda表达式函数式编程思想
函数式:
强调做事(不关心用什么对象,重写什么方法)
面向对象与函数表达式的对比
[Java] 纯文本查看 复制代码 // 面向对象方式的代码
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "新线程创建了");
}
}).start();
// 函数式编程的代码
new Thread(()-> {
System.out.println(Thread.currentThread().getName() + "新线程创建了");
}
).start();
Lambda标准格式
Lambda标准格式 表达式的3个部分
1.一些参数()
接口中抽象方法的参数列表,没参数就空着;有参数就写用逗号隔开
2.一个箭头->
将参数传递给方法体
3.一段代码 {}
重写接口抽象方法的方法体
格式:
(参数列表)->{重写方法的方法体}
Lambda省略格式和使用前提
省略原则:
可推导的都可省略 (凡是能根据前后代码能猜测出来的代码, 都可以省略不写)
可以省略的部分:
1. (参数列表): 参数"类型"可以省略
2. (参数列表): 如果参数只有1个, 则"类型"和"小括号"都可以省略 a -> sout(a)
3. {一些代码}: 如果只有一条代码, 则"大括号", "return", "分号"都可以"一起省略"
*函数式接口:
函数式接口"有且仅有一个抽象方法"
但函数式接口对于哪些方法算作抽象方法有特殊规定:
1. 有方法体的方法"不算作"抽象方法, 如默认方法, 静态方法, 私有方法
2. 抽象方法与java.lang.Object类中的方法定义相同的, 也"不算作"抽象方法3
因为任何实现本接口的实现类, 都会直接或间接继承java.lang.Object类的public的方法, 所以在创建实现类时其实不用重写该抽象方法, 也就不算作抽象方法
Lambda表达式的使用前提:
1. Lambda只能用于接口, 且"接口中有且仅有一个抽象方法"(也称为"函数式接口")
普通类, 抽象类不能用
2. 使用Lambda必须具有上下文推断
方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例
(简而言之: 作为参数类型的接口, 必须是函数式接口)
04-File类
绝对路径和相对路径
绝对路径:
以盘符开始的路径
如: "D:\\a\\hi.txt"
相对路径:
不以盘符开始的简化路径. 相对于项目的根目录
如: "a\\1.mp3", "123.txt"
File类: 构造方法
java.io.File类: 文件和目录的路径名的抽象表现形式, 主要用于文件和目录的创建, 查找和删除等操作
// 构造方法(创建了File对象, 并将其指向该路径. 不会真正在磁盘上创建这个文件)
File File(String pathname): 根据 路径字符串 封装一个File对象
File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
测试构造方法:
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
// File File(String pathname): 根据 路径字符串 封装一个File对象
File f1 = new File("z:\\z.txt"); // 不存在的路径也可以创建File对象
System.out.println(f1);
// File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装File对象
File f2 = new File("a\\", "a.txt"); // 相对路径也可以
System.out.println(f2);
// File File(File parent, String child): 根据 父路径的File对象 和 子路径 封装File对象
File f3 = new File(new File("d:\\"), "d.txt");
System.out.println(f3);
// 创建File对象后, 并不会在磁盘上创建文件或目录!
}
}
File类: 获取方法
java.io.File类
// 常用获取方法
String getAbsolutePath(): 返回此File的绝对路径名字符串
String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
String getName(): 获取File对象的文件名或目录名
long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
// String getAbsolutePath(): 返回此File的绝对路径名字符串
File f1 = new File("a.txt");
System.out.println(f1.getAbsolutePath()); // File对象是相对路径, 该方法可以获取到绝对路径
// String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)
System.out.println(new File("a.txt").getPath()); // 创建对象时是什么路径, 获取的就是什么
System.out.println(new File("d:\\a.txt").getPath());
// String getName(): 获取File对象的文件名或目录名
File f3 = new File("a\\b\\c\\d.txt");
System.out.println(f3.getName());
// long length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)
File f4 = new File("day08\\src\\com\\itheima\\test02\\Test.java"); // 相对路径
System.out.println(f4.length()); // 1431
}
}
File类: 判断方法
java.io.File类
// 常用判断方法
boolean exists(): 判断File对象代表的文件或目录是否实际存在
boolean isDirectory(): 判断File表示的是否为目录
boolean isFile(): 判断File表示的是否为文件
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
// boolean exists(): 判断File对象代表的文件或目录是否实际存在
File f1 = new File("day08\\src");
System.out.println(f1.exists());
// boolean isDirectory(): 判断File表示的是否为目录
File f2 = new File("day08\\src\\com\\itheima\\test03");
System.out.println(f2.isDirectory());
// boolean isFile(): 判断File表示的是否为文件
File f3 = new File("day08\\src\\com\\itheima\\test03\\Test.java");
System.out.println(f3.isFile());
}
}
File类: 创建删除方法
java.io.File类
// 常用创建删除方法
boolean createNewFile(): 当文件不存在时, 创建一个新的空文件
boolean delete(): 删除由此File表示的文件或目录. (删除目录时必须是空目录)
boolean mkdir(): 创建File表示的目录
boolean mkdirs(): 创建File表示的多级目录
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) throws IOException {
// 在当前的模块中创建a目录
/* File dirA = new File("day08\\a");
dirA.mkdir();
// 在a目录中创建b目录
File dirB = new File("day08\\a\\b");
dirB.mkdir();*/
// 以上两步可以合并为一步
File dirAB = new File("day08\\a\\b");
dirAB.mkdirs();
// 在b目录中创建b.txt文件和c.txt文件
File fileB = new File("day08\\a\\b\\b.txt");
fileB.createNewFile();
File fileC = new File("day08\\a\\b\\c.txt");
fileC.createNewFile();
// 删除c.txt文件
fileC.delete();
boolean result = new File("z:\\a").mkdirs(); // 磁盘不存在, 不会创建
System.out.println(result); // false
}
}
File类: 遍历目录方法
java.io.File类
// 常用获取目录中内容的方法
String[] list(): 获取当前File目录下的所有子文件或目录的名字数组
File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组
注意:
只能用表示目录的File对象调用
用文件的File对象, 或者路径不存在, 调用会报错
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
// 创建File对象指向当前模块
File module = new File("day08");
// listFiles()获取当前目录中的子文件和子目录的File数组
File[] files = module.listFiles();
for (File file : files) {
System.out.println(file);
}
// list(): 获取当前目录中的子文件和子目录的文件名数组
String[] list = module.list();
for (String s : list) {
System.out.println(s);
}
}
}
05 - 递归
递归的分类:
直接递归: 方法自己调用方法
间接递归: A方法调用B方法, B方法调用C方法, C方法调用A方法
递归打印多级目录
[Java] 纯文本查看 复制代码 [/b]public class Test {
public static void main(String[] args) {
File dir = new File("day08");
print(dir);
}
// 定义方法: 打印某个目录中所有路径
public static void print(File dir) { // 传入要打印的目录的File对象
// 先打印当前目录的路径
System.out.println(dir);
// 获取当前目录中的所有子文件和子目录
File[] files = dir.listFiles();
// 遍历数组
for (File file : files) {
// file代表子文件或者子目录, 具体是什么还需要判断
if (file.isFile()) {
// 如果是文件, 则打印文件
System.out.println(file);
} else {
// 如果是目录, 则递归调用当前方法, 打印"该子目录"中的所有路径
print(file); // 注意传入的是子目录对象!!!!!
}
}
}
}[b]
打印某个目录下所有java文件路径
[Java] 纯文本查看 复制代码 [/b][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size][/font][/size]public class Test {
public static void main(String[] args) {
print(new File("day08"));
}
// 定义方法: 打印某个目录中的.java文件
public static void print(File dir) {
// 先获取当前目录中的所有文件
File[] files = dir.listFiles();
// 遍历
for (File file : files) {
// 判断是文件还是目录
if (file.isFile()) {
// 是文件, 判断后缀
if (file.getName().toLowerCase().endsWith(".java")) {
// 是java文件, 打印
System.out.println(file);
}
} else if (file.isDirectory()) {
// 是目录, 递归调用方法
print(file);
}
}
}}[size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][size=2][font=微软雅黑][b]
FileFilter文件过滤器的使用和Lambda优化
[Java] 纯文本查看 复制代码 [/b][font=微软雅黑][size=3]public class Test {
public static void main(String[] args) {
print(new File("day08"));
}
// 打印指定目录中的.java文件
public static void print(File dir) {
// 获取当前目录中的文件, 使用过滤器
/*File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory() || name.toLowerCase().endsWith(".java");
}
});*/
// 使用Lambda表达式简化
File[] files = dir.listFiles((d, name) -> new File(d, name).isDirectory() || name.toLowerCase().endsWith(".java"));
// 遍历
for (File file : files) {
if (file.isFile()) {
// 是文件, 则打印
System.out.println(file);
} else if (file.isDirectory()) {
// 是目录, 则递归
print(file);
}
}
}
}[/size][/font][b]
06 - IO流
IO流: 输入(Input)输出(Output)流
流: 数据流
输入: 从硬盘(文件)读取到内存(Java程序)
输出: 从内存(Java程序)写入到硬盘(文件)
(入和出都是相对于内存来说的)
IO流的分类:
字节流 (读写字节: byte, 可以读写所有类型的文件, 包括视频, 图片, 音频, 文本等)
字节输入流: java.io.InputStream 抽象类
字节输出流: java.io.OutputStream 抽象类
字符流 (读写字符: char, String, 只能读写文本文件)
字符输入流: java.io.Reader 抽象类
字符输出流: java.io.Writer 抽象类
java.io.OutputStream抽象类: 字节输出流 (顶层类)
// 成员方法
void close() :释放资源
void flush() :刷新缓冲区(对于字节流来说没有作用)
// 写字节的成员方法
abstract void write(int b): 一次写一个字节 (参数int便于传递byte的整数不用强转)
void write(byte[] b): 一次写一个字节数组
void write(byte[] b, int offset, int len): 一次写一个字节数组的一部分
java.io.FileOutputStream类: 文件字节输出流 (向文件写数据)
// 构造方法
FileOutputStream(String name): 通过文件路径创建文件字节输出流
FileOutputStream(File file): 通过File对象创建文件字节输出流
构造方法的作用:
1. 创建一个FileOutputStream对象
2. 根据构造方法传递的路径, 在磁盘上创建一个空文件 ("如果文件存在则会清空数据")
3. 将创建的FileOutputStream对象指向这个磁盘上的文件
字节输出流: 一次写一个字节到文件
写数据的原理:
Java程序 -> JVM虚拟机 -> OS操作系统 -> OS调用写数据的方法 -> 将数据写入文件
使用FileOutputStream写数据到文件
[Java] 纯文本查看 复制代码 [/b]public class Test {
public static void main(String[] args) throws IOException { // 异常先声明抛出
// 1. 创建流对象
FileOutputStream fos = new FileOutputStream("day09\\testOutputStream1.txt");
// 2. 写数据
fos.write(97);
fos.write(98);
fos.write(99);
// 3. 释放资源
fos.close();
}
}[b]
java.io.FileOutputStream类: 文件字节输出流
// 带有 续写 功能的构造方法, 不会清空文件
FileOutputStream(String name, boolean append): 通过文件路径创建流, true可以续写
FileOutputStream(File file, boolean append): 通过File对象创建流, true可以续写
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) throws IOException {
// 创建流对象
FileOutputStream fos = new FileOutputStream("day09\\testOutputStream2.txt", true);//true或flase
// 循环写入
for (int i = 0; i < 5; i++) {
fos.write("你好".getBytes());
fos.write("\r\n".getBytes());
}
// 释放资源
fos.close();
}
}
|
|