线程之间的通信:概念是, 当多个线程在处理同一个资源,但是处理的动作(线程的任务)不同,这个时候要线程相互协作,这就需要线程间的进行通信。以此来帮助我们达到多线程来共同操作同一份数据。
等待与唤醒机制(线程之间的通信的一种方式):wait()。。。notify/notifyAll。 notify只唤醒一个线程,唤醒那个等待得最久的那个线程。 notifyAll会唤醒所有的等待线程。
Lambda表达式:写法是 (这里面写参数列表)->{这里面写方法体,就是我们重写方法的代码}
Lambda表达式只能用在函数式接口中,而什么是函数式接口呢,就是说这个接口中只有一个抽象方法。
():接口中抽象方法的参数列表,多个参数用逗号分隔,没有参数就空着
—>:传递参数的意思,就是把参数传递给{}。
{}:重写接口抽象方法的代码。
Lambda表达式使用注意事项:1、Lambda表达式是可推导,可以省略的。就是说凡是根据上下文推导出来的内容,都可以省略。可省略的内容包括:
(参数列表):括号中参数列表的数据类型相同,可以省略不写;
(参数列表):括号中的参数列表如果只有一个,那么类型和()都可以省略;
{一些代码}:如果{}中只有一行代码,无论是否有返回值,都可以省略{}和分号,return可以省略。
注意在省略的时候要省略的话就要这三项一起省略。
Lambda的使用前提:要求接口中有且只有一个抽象方法。
必须具有上下文推断。
函数式编程:面对想的思想。
线程池:
Executors中的静态方法:
static ExecutorsService newFixedThreadPool(int nThread)创建一个可重复利用的固定线程数的线程池。
参数 int nThread :创建的线程池中线程的数量。
返回值 ExecutorService接口,返回的是ExecutorService接口的实现类对象,我们可以使用ExecutorService接口接收(面向接口编程)。
用来从线程池从线程池获取线程,调用start方法,执行任务。
submit(runnerable task)提交一个Runnerable任务用于执行
实现步骤:
1、用线程尺工厂类Executors里面提供的静态方法newFixedThreadPool生产一个指定线程数量的线程池。
2、创建一个实现类,让他实现Runnerable节口。
3、调用ExecutorService中的方法 submit,传递线程任务,开启线程,执行run方法
4、调用ExecutorService中的方法shutdown 关闭线程池(不建议使用)
File类:操作文件
File类中有许多操作计算机的文件的方法。
学了File类要记住三个单词:file (文件) directory(目录) path(路径)
File中的静态方法:
static String pathSeparator 与系统有关的路径分隔符,为了方便,它被表示为一个字符串。
static char pathSeparatorChar 与系统有关的路径分隔符。
static String separator 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
static char separatorChar 与系统有关的默认名称分隔符。
路径分隔符 windows:分号 ; linux:冒号
文件分隔符 windows:反斜杠 linux:正斜杠
路径:绝对路径和相对路径
绝对路径:是一个完整的路径
相对路径:是一个简化的路径,指的是相当于当前项目的根目录。如果使用当前项目的根目录,路径可以简化书写。(可以省略根目录 )就是说不以盘符或者是反斜杠开头的是相对路径。
File 中的构造方法。
File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File实例
String pathName 字符串的路径名称
路径可以是以文件结尾,也可以是文件夹结尾
路径可以是相对路径也可以是绝对路径
路径可以是存在的,也可是不存在的。
创建File对象,只是把字符串路径封装为File对象,不考虑真假问题。
File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
将路径分为两部分,父路径和子路径。使用起来可以非常灵活。父路径和子路径都可以改变。
File(File parent, String child) 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
这个构造方法也是将路径分为两部分,父路径和子路径都可以改变。
父路径是File类型,可以使用File中方法来对路径进行一些操作;在使用路径创建对象。 。。
boolean exists() 测试此抽象路径名表示的文件或目录是否存在。
boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。
boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。 用于判断构造方法给定的路径是否是以文件夹结尾
boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。 测试此抽象路径名表示的文件是否是一个目录。 用于判断构造方法给定的路径是否是以文件夹结尾
isDirectory 和isFile是互斥的。,整两个方法的前提是路径必须存在,否则都返回为false
File类的创建和删除功能:
boolean createNewFile() 当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件
这个方法只能创建文件。声明抛出了IOException ,我们调用了这个方法就必须处理这个异常。
创建文件的时候要创建在已经存在的文件夹里面。不会帮我们创建文件夹。
boolean delete() 删除此抽象路径名表示的文件或目录。此方法可以删除构造方法给的文件夹或者是文件。 这个方法是直接在硬盘中删除文件,不会收到回收站。 删除的时候谨慎一点。
在使用delete删除文件夹的时候如果文件夹里面有文件,那么就删除不成功。它只能删除空的文件夹。
boolean mkdir() 创建此抽象路径名指定的目录。只能创建单级文件夹,不能创建文件。 文件夹路径在工造方法中给出
boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。 能创建单级文件夹也能创建多级文件夹。不能创建文件。 路径在构造方法中给出。
对目录进行遍历:
String[] list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。遍历出当前文件夹中的第一层目录
File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。 这个方法会获取目录中的所有文件/文件夹 这个返回的是一个File类型的对象。
注意:list方法和listFiles方法遍历的是构造方法给出的目录。
如果构造方法给出的目录的路径不存在,会抛出空指针异常
如果构造方法给出的目录不是一个目录也会报空指针异常。
递归:就是方法自己调用自己。
递归分为直接递归和简介递归。
递归的使用前提:当使用方法的时候,方法的主题不变,每次调用方法的参数不变。
构造方法不能使用递归。
使用递归的时候需要明确的:1、递归的结束条件 2、递归的目的
字节输出流(OutputStream) 字节输入流(InputStream)
字符输入流(Reader) 字符输出流(writer)
字节输出流(OutputStream)是所有字节输出流的超类:
定义了一些成员方法:
void close() 关闭此输出流并释放与此流有关的所有系统资源。
void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)将指定的字节写入此输出流。
FileOutputStream:继承了OutputStream 可以把内存中的数据写入到硬盘的文件中。
其中的构造方法:
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append)创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream中的一些成员方法:
参数:string name:创建一个FileOutputStream对象,并且绑定文件的路径。
File file 绑定的是一个对象。
在调用这个构造方法的时候:
1、如果没有我么指定的文件。它会帮我们创建一个文件,它不会帮我们创建文件夹。
2、构造方法会把我们创建的对象指向创建好的文件。
我们写入硬盘的原理(java程序->JVM->os->os调用写数据的方法->把数据写入到文件中)
void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
void write(int b) 将指定字节写入此文件输出流。
void close() 关闭此文件输出流并释放与此流有关的所有系统资源。
使用时的步骤:
1、创建一个FileoutputStream对象
2、调用FileOutputStream中的write方法
3、结束后将这个流关掉 使用 close()方法。
再一次写多个字符的时候:如果第一个字节是正数(0-127)那么显示的时候会查ASCII表;如果写的第一个字节是负数,两个字节会组成一个中文显示。
FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。
FileInputStream 字节输入流(相对于java程序来说):他是InputStream的子类,InputStream是所有字节输入流的超类。这个方法就是把文件中的数据读取到内存中使用。
读取数据的时候的原理:java->JVM(java虚拟机)->os->调用读取数据的方法->读取文件。
该类中的方法有:
int read() 从此输入流中读取一个数据字节。
int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
int read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
字节输入流一次读取多个字节的方法:明确两个东西。1、方法的参数byte[]的作用是什么。 2、方法的返回值int是什么。
String中的方法
String(byte[] byte)把字节数组,转换成字符串
String(byte[],int offset, int length ).
当我么们使用读和写一起复制文件的时候,关流的时候要先关掉写的流,因为当我们写完了那么一定读完了,。(这个叫做二流对接)
Reader:字符输入流 是字符输入流的最顶层的父类。
int read() 读取单个字符。
int read(char[] cbuf) 将字符读入数组。
void close() 关闭该流并释放与之关联的所有资源。
其中的构造方法:
protected Reader() 创建一个新的字符流 reader,其重要部分将同步其自身的 reader。
使用的时候也是分为三个步骤:
1、创建你File Reader对象,构造方法中绑定读取的数据圆
2、使用FileReader对象中的方法读取文件
3、释放资源。
Writer 字符输出流,是所有字符输出流的最顶层父类
里面共性的方法:
void close() 关闭此流,但要先刷新它。。
void flush() 关闭此流,但要先刷新它。
void write(char[] cbuf)写入字符数组。
void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(String str) 写入字符串。
void write(String str, int off, int len)写入字符串的某一部分。
FileWriter 是Writer的子类
字符输出流使用的步骤:
1、首先创建一个FileWriter对象,并且绑定输出源。
2、使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
3、使用FileWriter中的方法flash,把内存缓冲区中的数据刷新到文件中去
4、释放资源。
关于flash 输出流都有flash。
IO中流的异常用try catch finall来解决:
格式:try{可能出现异常的代码}catch(异常变量 变量名){异常处理逻辑}finall(一定会执行的代码 释放资源)
注意一个作用域的问题:finally中的对象会报红把定义变量的拿到Try外边去定义在finally中就能使用了。
在JDK7中的新特性:try(){}catch(){} 可以在try后边的小括号中创建对象,创建的对象在整个try catch中有效,并且使用完成后会关闭流,我们就不用再用finally关闭了。
properties集合是个双列集合,它implments Map<key,value>,他是唯一一个与IO流结合的集合。
可以使用Properties集合中的方法 store,把集合中的临时文件持久化的写入到硬盘中存储
void store(OutputStream out, String comments) 以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。
void store(Writer writer, String comments)以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。
其中的comments是注释 一般用空字符串“”
以可私用Properties集合中的方法Load 把硬盘中的文件(键值对)读取到集合中使用。
void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。
void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
properties其中的方法:
Object setProperty(String key, String value) 调用 Hashtable 的方法 put。
String getProperty(String key, String defaultValue)用指定的键在属性列表中搜索属性
Set<String> stringPropertyNames() 返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
匿名对象中的流用完之后就关闭了。
缓冲流:BufferedInputStream字节缓冲输入流
BufferedOutputStream字节缓冲输出流
BufferedWriter字符缓冲输出流
BufferedReader字节缓冲输入流
它们分别继承了字节流和字符流。
BufferedOutputStream的使用步骤:
1、创建一个FileOutPutStream对象,构造方法绑定要输出的目的地
2、创建一个BufferedOutputStream对象,在构造方法中传入FileOutPutStream对象,提高BufferedOutputStream对象效率
3、使用BufferedOutputStream对象调write方法,把数据写道缓冲区中
4、使用BufferedOutputStream对象中的方法flush,把缓冲区的数据刷新到文件中去。
5、释放资源(close)
其他的三个方法和这个的方法类似
字节流:
GBK 中文码表 使用两个字节存储一个中文;UTF-8 国际标准码表 使用三个字节存储一个中文。
出现乱码的原因就是使用的码表不一致。
为了解决码表不一致的时候残生乱码的问题,使用转换流:
InputStreamReader(是字节流向字符的桥梁)它可以使用指定的charSet读取字节并解码为字符。
输入流的构造方 InputStreamReader(FileInputStream fis,”码表类型“);
OutputStreamWriter(是字符流向字节的桥梁)可以使用指定的charSet将要写入的流中的字符编码成字节。
他的构造方法:
OutputStreamWriter(OutputStream out) 创建使用默认字符编码的OutputStreamWriter
OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter
它里面的方法:
void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(int c)写入单个字符。
void write(String str, int off, int len) 写入字符串的某一部分。
void close() 关闭此流,但要先刷新它。
void flush() 刷新该流的缓冲。
网络编程三要素:协议、IP地址、端口
软件结构:分为c/s结构和b/s结构(分别是客户端/服务器结构 还有是浏览器/服务器结构)这两种结构都离不开网络。
网络通信协议:就是一种规则。
(协议有两种)TCP/IP协议和UDP协议。传输控制协议/因特网互联协议。它定义了如何连入因特网,以及数据如何在他们之间传输的标准。
TCP协议是比较安全的协议(有三次握手)在传输数据之前会先建立发送端和接受端的逻辑连接,然后再传输数据。再数据传输的准备阶段会进行三次确认,就是三次握手。
UDP协议是无连接通信协议,就是说数据在传输时数据的发送端和接受端不建立逻辑连接,简单来说,当一台计算机在向另一台计算机发送数据时不会查看该计算机是否存在。没有TCP协议那么安全的一种协议。该协议数据被限制在64kb。
IP地址:给在网络中的计算机一个编号。分为IPV4 和IPV6两种,分别是4个字节和6个字节的。
我们将一个信息准确无误的发送到对应的软件上,是通过端口号来实现的。
端口号是由两个字节组成的,取值在0~65535之间,他是一个逻辑端口,我们无法直接看到,只有通过一些软件查看。1024之前的端口号不能使用,以及被系统分配给已知的网络软件了。端口号其实就是相当于门牌号。
常用的端口号:1、80端口 网络端口 正确的网址 www。baidu.com:80(不写就是默认的80),如果写成其他的端口号就访问不了。
2、数据库 mysql:3306 oracle:1521
3、Tomat服务器:8080
通信的步骤:服务器要先启动;服务器不会主动请求客户端;必须使用客服端请求服务器;客户端和服务器就会建立一个逻辑连接;而这个连接中包含一个对象;这个对象就是IO对象;客服端和服务器就可以使用IO对象进行通信;通信数据不仅仅有字符所以IO对象是字节流对像。
TCP中存在问题和注意事项:在服务器端要明确两件事情:1、多个客户端可以同时和多个客户端同时进行交互,服务器必须明确和哪个客户端进行交互,在服务器中有一个方法accept客户端获取到请求的客服端对象。2、多个客户端在和服务器进行交互的时候就要使用多个IO流对象。服务器是没有IO对象,服务器是用客户端的流和客服端进行交互。
表示客服端的类;Socket 此类实现客户端套接字。套接字是两台机器间的通信端点
套接字:包含了IP地址和端口号的网络单位
Socket的构造方法:
Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。 host:服务器的主机名称/服务器的IP地址 port:服务器的端口
Socket的成员方法:
outputStream getOutputStream() 返回此套接字的输出流
InputStream getInputStream()返回此套接字的输入流
实现步骤:
1、创建一个客户端对象Socket,构造方法绑定服务器的IP地址和端口
2、使用Socket中的方法getOutputStream获取网络字节输出流OutputStream对象
3、使用网络字节输出流OutputStream对像中的方法write,给服务器发送数据
4、使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
5、使用网络字节输入流InputStream对象中的read()方法
6、返回给客户端一个数据表示服务器经接受到了。
|
|