A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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的输出目的地为参数的打印流










0 个回复

您需要登录后才可以回帖 登录 | 加入黑马