目录
一、I/O流
文件流:文件在程序中是以流的形式来操作的
流(stream):数据在文件和程序之间经历的路径
输入流:程序(内存)<-------- 文件(磁盘) 输出流:程序(内存) --------> 文件(磁盘)
1、文件
(1)创建文件(JAVA中,目录也被当作文件),File类实现了Serializable和Comparable接口
//创建文件
public void create1() {
File file = new File("d:\\new1.txt");
try {
file.createNewFile(); //创建文件:createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public void create2() {
File file1 = new File("d:\\");
File file2 = new File(file1,"new2.txt");
try {
file2.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public void create3() {
File file = new File("d:\\","new3.txt");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//创建目录
public void create1() {
File file = new File("d:\\new");
file.mkdir(); //创建一级目录:mkdir();
}
public void create2() {
File file = new File("d:\\new\\new");
file.mkdirs(); //创建多级目录:mkdirs();
(2)文件常用方法
//获取文件名字
file.getName();
//获取绝对路径
file.getAbsolutePath();
//获取文件父级目录
file.getParent();
//获取文件大小
file.length();
//判断是不是一个文件
file.isFile();
//判断是不是一个目录
file.isDirectory();
//判断文件\目录是否存在
file.exists();
//删除一个文件\目录
file.delete();
2、流的分类
按操作数据单位不同分为:字节流(二进制文件,按字节),字符流(文本文件,按字符)
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:
节点流:可以从一个特定的数据源读写数据
处理流(包装流):包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出,使用了修饰器设计模式,不会直接与数据源相连
3、InputStream抽象类,字节输入流
(1)FileInputStream节点流
public void readFile() {
FileInputStream file = null;
try {
file = new FileInputStream("d:\\file.txt");
//从该输入流读取一个字节数据
//如果读取正常,返回实际读取的字节数
//如果返回-1,表示读取完毕
int readDate = 0;
while ((readDate = file.read()) != -1) {
System.out.print((char) readDate);
}
file = new FileInputStream("d:\\file.txt");
//从该输入流读取最多字节数组长度的字节数据到字节数组
//如果读取正常,返回实际读取的字节数
//如果返回-1,表示读取完毕
byte[] b = new byte[8];
int readLength = 0;
while ((readLength = file.read(b)) != -1) {
System.out.print(new String(b, 0, readLength));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件流,释放资源
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2)BufferedInputStream处理流
public void readFile() {
BufferedInputStream file = null;
try {
//处理流对象要求InputStream类及其子类的对象
file = new BufferedInputStream(new FileInputStream("d:\\file.txt"));
//方法与FileInputStream类似
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件流,只需关闭外层流,底层会自动关闭节点流
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(3)ObjectInputStream处理流
一个类要想可序列化那么这个类和这个类成员属性对应的类都必须实现Serializable接口(是一个标记接口,接口没有方法)或Externalizable接口
public void readFile() throws ClassNotFoundException {
try {
ObjectInputStream file = new ObjectInputStream(new FileInputStream("d:\\file.dat"));
//读取(反序列化)的顺序需要和保存(序列化)的顺序一致
//static或transient修饰的成员不会被序列化
file.readInt();
file.readBoolean();
file.readChar();
file.readDouble();
file.readUTF();
Object o = file.readObject();
//如果我们需要调用对象方法,需要向下转型,并且对象类的定义,应该在此类可以引用的位置
Dog d = (Dog) o;
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
4、OutputStream抽象类,字节输出流
(1)FileOutputStream节点流
public void writeFile() {
FileOutputStream file = null;
try {
//如果不存在此文件,会创建文件,构造器后面加了true,表示写入会追加而不是覆盖
file = new FileOutputStream("d:\\file.txt", true);
//写入一个字节
file.write('A');
//写入一个字节数组
byte[] b = {'B','C'};
file.write(b);
file.write(b, 0, b.length);
//写入一个字符串
String s = "Hello";
file.write(s.getBytes());
file.write(s.getBytes(), 0, s.length());
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
(2)BufferedOutputStream处理流
public void writeFile() {
BufferedOutputStream file = null;
try {
//处理流对象要求OutputStream类及其子类的对象
file = new BufferedOutputStream(new FileOutputStream("d:\\file.txt", true));
//方法与OutputStream类似
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
(3)ObjectOutputStream处理流
public void writeFile() {
try {
ObjectOutputStream file = new ObjectOutputStream(new FileOutputStream("d:\\file.dat"));
file.writeInt(100);
file.writeBoolean(true);
file.writeChar('a');
file.writeDouble(1.1);
file.writeUTF("你好");
file.writeObject(new Dog());
file.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
(4)PrintStream打印流
public void PrintFile() throws IOException {
PrintStream p = System.out;
//保准输出,显示器
p.print(1);
//print底层使用的是write,因此可以直接调用write
p.write("你好".getBytes());
p.close();
//修改打印流输出的位置到文件中
System.setOut(new PrintStream("d:\\word.txt"));
System.out.println("123");
}
5、Reader抽象类,字符输入流
(1)FileReader节点流
public void readFile() {
FileReader file = null;
try {
file = new FileReader("d:\\file.txt");
int readDate = 0;
while ((readDate = file.read()) != -1) {
System.out.print((char) readDate);
}
file = new FileReader("d:\\file.txt");
char[] c = new char[8];
int readLength = 0;
while ((readLength = file.read(c)) != -1) {
System.out.print(new String(c, 0, readLength));
}
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
(2)BufferedReader处理流
public void readFile() {
BufferedReader file = null;
try {
file = new BufferedReader(new FileReader("d:\\file.txt"));
//readLine按行读取文件
//如果返回null,表示读取完毕
String line;
while ((line = file.readLine()) != null) {
System.out.println(line);
}
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
(3)InputStreamReader转换流
可以指定字节流的编码格式, 并包装成字符流
public void readFile() throws ClassNotFoundException {
try {
BufferedReader b = new BufferedReader(new InputStreamReader(new FileInputStream("d:\\file.txt"),"gbk"));
String s = b.readLine();
System.out.println(s);
b.close();
} catch (IOException e) {
e.printStackTrace();
}
}
6、Writer抽象类,字符输出流
(1)FileWriter节点流
public void writeFile() {
FileWriter file = null;
try {
//如果不存在此文件,会创建文件,后面加了true,写入会追加而不是覆盖
file = new FileWriter("d:\\file.txt", true);
//写入一个字节
file.write('A');
//写入一个字节数组
char[] b = {'B','C'};
file.write(b);
file.write(b, 0, b.length);
//写入一个字符串
String s = "Hello";
file.write(s);
file.write(s, 0, s.length());
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
(2)BufferedWriter处理流
public void writeFile() {
BufferedWriter file = null;
try {
file = new BufferedWriter(new FileWriter("d:\\file.txt", true));
//插入一个和系统相关的换行符
file.newLine();
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
(3)OutputStreamWriter转换流
public void writeFile() throws ClassNotFoundException {
try {
BufferedWriter b = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:\\file.txt",true),"gbk"));
b.write("你好");
b.close();
} catch (IOException e) {
e.printStackTrace();
}
}
(4)PrintWriter打印流
public void PrintFile() throws IOException {
PrintWriter p1 = new PrintWriter(System.out);
//输出到显示器
p1.print(1);
p1.close();
//输出到文件
PrintWriter p2 = new PrintWriter(new FileWriter("d:\\word.txt"));
p2.print(456);
p2.close();
}
7、Properties类
public void File() throws IOException {
//专门用于读写配置文件的集合类
//格式:健=值 键值对不需要有空格,也不需要引号,默认String
Properties p = new Properties();
//创建配置文件
p.setProperty("A","a");
p.setProperty("你好","世界"); //保存的是中文的unicode码值
p.store(new FileOutputStream("d:\\set.properties"),"注释");
//加载配置文件
p.load(new FileReader("d:\\set.properties"));
//把k-v输出到控制台
p.list(System.out);
//根据key获取对应的值
p.getProperty("A");
}
二、线程
(1)线程由进程创建,是进程的一个实体,一个进程可以拥有多个线程
(2)单线程:同一个时刻,只允许执行一个线程
(3)多线程:同一个时刻,允许执行多个线程
(4)并发:同一个时刻,多个任务交替执行
(5)并行:同一个时刻,多个任务同时执行
(6)同步:当有一个线程对内存进行操作时,其他线程都不可以对这个内存就像操作
1、创建线程
(1)继承Thread类:该类就可以当作线程使用,重写Runnable接口的run方法,Thread类实现Runnable接口
public class TestA {
public static void main(String[] args) {
//此调用仍是main线程,run方法就是个普通的方法,没有真正的启动一个线程
//run方法执行之后才会向下执行
//new A().run();
//start方法会调用start0方法,调用后,该线程并不一定会立即执行,只是将线程变成可运行状态
//具体什么时候执行,取决于CPU,由CPU统一调度,最终会执行A的run方法
//当执行run方法时,开启一个进程,启动了main主线程
//当main线程start一个子线程Thread-0后,main线程不会阻塞,会继续执行
//start0是本地方法,是JVM调用的,真正实现多线程的效果,是start0而不是run
//当主线程结束,不意味着进程结束,可能还有子线程在运行
new A().start();
while(true) {
//输出主线程名 main
System.out.println(Thread.currentThread().getName());
//让主线程休眠,实现每隔一秒输出一次,单位是毫秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class A extends Thread{
@Override
public void run() {
while(true) {
//输出子线程名 Thread-0
System.out.println(Thread.currentThread().getName());
//让子线程休眠,实现每隔一秒输出一次,单位是毫秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(2)实现Runnable接口:该类就可以当作线程使用,重写Runnable接口的run方法
public class TestA {
public static void main(String[] args) {
//Runnable没有start方法,需要创建Thread对象,把A对象放入Thread
new Thread(new A()).start();
}
}
class A implements Runnable {
@Override
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2、终止线程
(1)当线程完成任务后,会自动退出
(2)通过使用变量来控制run方法退出的方式停止线程,即通知方式
public class TestA {
public static void main(String[] args) throws InterruptedException {
A a = new A();
a.start();
//主线程休眠3秒,再通知a退出
Thread.sleep(1000*3);
a.loop = false;
}
}
class A extends Thread {
boolean loop = true;
@Override
public void run() {
while(loop){
System.out.println(1);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
3、线程常用方法
(1)线程优先级的范围:MIN_PRIORITY = 1; NORM_PRIORITY = 5; MAX_PRIORITY = 10;
(2)interrupt:中断线程,但没有真正的结束线程,一般用于中断正在休眠的线程
(3)sleep:静态方法,使当前线程休眠
public class TestA {
public static void main(String[] args) throws InterruptedException {
A a = new A();
a.setName("A");
a.getName();
a.setPriority(Thread.MAX_PRIORITY);
a.getPriority();
a.getState();
a.start();
a.run();
a.interrupt();
try {
a.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class A extends Thread {
@Override
public void run() {
}
}
public class TestA {
public static void main(String[] args) throws InterruptedException {
A a = new A();
a.start();
for (int i = 1; i <= 20; i++) {
System.out.println("主线程" + i);
Thread.sleep(1000);
if (i == 5) {
Thread.yield(); //yield:礼让,让其他线程执行,但礼让不一定成功
a.join(); //join:插队,先执行完调用join方法线程的所有任务
}
}
}
}
class A extends Thread {
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
System.out.println("子线程" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TestA {
public static void main(String[] args) throws InterruptedException {
A a = new A();
a.setDaemon(true); //子线程设为守护线程,当所有用户线程结束,守护线程也结束
a.start();
for (int i = 1; i <= 5 ; i++) {
System.out.println("主线程");
Thread.sleep(1000);
}
}
}
class A extends Thread {
@Override
public void run() {
for (; ; ) {
System.out.println("子线程");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4、线程状态
NEW:尚未启动的线程
RUNABLE:在JVM中执行的线程,又分Ready和Running
BLOCKED:被阻塞等待监视器锁定的线程
WAITING:正在等待另一个线程执行特定动作的线程
TIMED_WAITING:正在等待指定等待时间的线程
TERMINATED:已退出的线程
5、线程同步机制 synchronized
(1)同步代码块,互斥锁在this对象
public class TestA {
public static void main(String[] args) throws InterruptedException {
new Thread(new A()).run();
new Thread(new A()).run();
new Thread(new A()).run();
}
}
class A implements Runnable {
private static boolean loop = true;
private static int n = 100;
public void m() {
synchronized (this) {
if (n <= 0) {
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(--n);
}
}
@Override
public void run() {
while (loop) {
m();
}
}
}
(2)同步方法
public class TestA {
public static void main(String[] args) throws InterruptedException {
new Thread(new A()).run();
new Thread(new A()).run();
new Thread(new A()).run();
}
}
class A implements Runnable {
private static boolean loop = true;
private static int n = 100;
public synchronized void m() {
if (n <= 0) {
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(--n);
}
@Override
public void run() {
while (loop) {
m();
}
}
}
6、互斥锁
保证共享数据操作的完整性,每个对象都对应于一个可称为“互斥锁”的标记,关键字synchronized与对象的互斥锁联系,当某个对象用synchronized修饰时,用来保证任一时刻,只能有一个线程访问该对象。
同步的局限性:程序的执行效率降低
(1)非静态同步方法的锁可以是this,也可以是其他对象(需求是同一个对象的)
class A implements Runnable {
private static boolean loop = true;
private static int n = 100;
public void m() {
synchronized (this) {
if (n <= 0) {
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(--n);
}
}
@Override
public void run() {
while (loop) {
m();
}
}
}
class A implements Runnable {
private static boolean loop = true;
private static int n = 100;
Object o = new Object();
public void m() {
synchronized (o) {
if (n <= 0) {
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(--n);
}
}
@Override
public void run() {
while (loop) {
m();
}
}
}
(2)静态同步方法的锁为当前类本身,当前类.class
class A implements Runnable {
private static boolean loop = true;
private static int n = 100;
public static void m() {
synchronized (A.class) {
if (n <= 0) {
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(--n);
}
}
@Override
public void run() {
while (loop) {
m();
}
}
}
7、死锁
多个线程都占用了对方的锁资源,不肯相让,导致死锁
public class TestA {
public static void main(String[] args) throws InterruptedException {
A a1 = new A(true);
A a2 = new A(false);
a1.start();
a2.start();
}
}
class A extends Thread {
static Object o1 = new Object();
static Object o2 = new Object();
boolean flag;
public A(boolean flag){
this.flag=flag;
}
@Override
public void run() {
if (flag){
synchronized (o1){
System.out.println(Thread.currentThread().getName()+"进入1");
synchronized (o2){
System.out.println(Thread.currentThread().getName()+"进入2");
}
}
}else {
synchronized (o2){
System.out.println(Thread.currentThread().getName()+"进入2");
synchronized (o1){
System.out.println(Thread.currentThread().getName()+"进入1");
}
}
}
}
}
8、释放锁
(1)当前线程执行结束时,释放锁
(2)当前线程遇到break,return时,释放锁
(3)当前线程遇到未处理的异常时,释放锁
(4)当前线程执行了对象的wait方法,当前线程暂停,释放锁
(5)程序调用了sleep,yield方法暂停当前进程的执行,不释放锁
(6)其他线程调用了该线程的suspend方法将该线程挂起,不释放锁
三、网络编程
1、InetAddress
//获取本机的对象
InetAddress i1 = InetAddress.getLocalHost();
System.out.println(i1);
//根据一个主机名获取对象
InetAddress i2 = InetAddress.getByName("MmGz");
System.out.println(i2);
//根据一个域名获取对象
InetAddress i3 = InetAddress.getByName("www.baidu.com");
System.out.println(i3);
//根据对象,获取主机名或域名
System.out.println(i3.getHostName());
//根据对象,获取对应的地址
System.out.println(i3.getHostAddress());
2、TCP编程
(1)字节流
//服务端
public class Test1 {
public static void main(String[] args) throws IOException {
//在本机的9999端口监听,等待连接,要求本机没有其它服务在监听9999
ServerSocket s1 = new ServerSocket(9999);
//ServerSocket可以通过accept方法返回多个Socket
//没有客户端连接9999端口时,程序会阻塞,等待连接
//如果有客户端连接,则会返回Socket对象,程序继续
Socket s2 = s1.accept();
//得到和Socket对象关联的输入流
InputStream i = s2.getInputStream();
int readLengeh = 0;
while ((readLengeh = i.read()) != -1) {
System.out.print((char) readLengeh);
}
//接收结束
s2.shutdownInput();
//接收hello1后,发送回一个hello2
OutputStream o = s2.getOutputStream();
o.write("hello2".getBytes());
//必须关闭
s1.close();
s2.close();
i.close();
o.close();
}
}
//客户端
public class Test2 {
public static void main(String[] args) throws IOException {
//连接本机的9999端口,如果连接成功,返回Socket对象
Socket s = new Socket(InetAddress.getLocalHost(),9999);
//得到和Socket对象关联的输出流
OutputStream o = s.getOutputStream();
//发送hello1
o.write("hello1".getBytes());
//结束发送
s.shutdownOutput();
//接收hello2
InputStream i = s.getInputStream();
int readLengeh = 0;
while ((readLengeh = i.read()) != -1) {
System.out.print((char)readLengeh);
}
//必须关闭
o.close();
s.close();
i.close();
}
}
(2)字符流
//服务端
public class Test1 {
public static void main(String[] args) throws IOException {
//在本机的9999端口监听,等待连接,要求本机没有其它服务在监听9999
ServerSocket s1 = new ServerSocket(9999);
//ServerSocket可以通过accept方法返回多个Socket
//没有客户端连接9999端口时,程序会阻塞,等待连接
//如果有客户端连接,则会返回Socket对象,程序继续
Socket s2 = s1.accept();
//得到和Socket对象关联的字节输入流
InputStream i = s2.getInputStream();
//将字节流转换位字符流
BufferedReader b1 = new BufferedReader(new InputStreamReader(i));
System.out.println(b1.readLine());
//接收hello1后,发送回一个hello2
OutputStream o = s2.getOutputStream();
BufferedWriter b2 = new BufferedWriter(new OutputStreamWriter(o));
b2.write("hello2");
b2.newLine();
b2.flush();
//必须关闭
b2.close();
b1.close();
s2.close();
s1.close();
}
}
//客户端
public class Test2 {
public static void main(String[] args) throws IOException {
//连接本机的9999端口,如果连接成功,返回Socket对象
Socket s = new Socket(InetAddress.getLocalHost(),9999);
//得到和Socket对象关联的字节输出流
OutputStream o = s.getOutputStream();
//将字节流转换位字符流
BufferedWriter b1 = new BufferedWriter(new OutputStreamWriter(o));
//发送hello1
b1.write("hello1");
//插入一个换行符,表示写入内容结束,要求对方使用readline来读
b1.newLine();
//使用字符流,需要手动刷新,否则数据不会写入数据通道
b1.flush();
//接收hello2
InputStream i = s.getInputStream();
BufferedReader b2 = new BufferedReader(new InputStreamReader(i));
System.out.println(b2.readLine());
//必须关闭
b2.close();
b1.close();
s.close();
}
}