转换流
含义
:字节流装成字符流
种类
InputSteamReader
将字节输入流转为字符输入流
OutputStreamWriter
将字节输出流转为字符输出流
案例一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class _01ByteInputToCharInput { public static void main(String[] args) { BufferedReader bufferedReader=null; try { InputStream inputStream = new FileInputStream("C:\\11.txt"); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); bufferedReader = new BufferedReader(inputStreamReader); System.out.println(bufferedReader.readLine()); } catch (IOException e) { e.printStackTrace(); }finally { if(bufferedReader!=null){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
|
案例二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class _02ByteOutToCharOutput { public static void main(String[] args) { OutputStreamWriter outputStreamWriter=null; try { OutputStream outputStream = new FileOutputStream("C:\\22.txt",true); outputStreamWriter = new OutputStreamWriter(outputStream); outputStreamWriter.write("\r\n中国你好\r\n"); outputStreamWriter.write("台湾你好\r\n"); } catch (IOException e) { e.printStackTrace(); }finally { if(outputStreamWriter!=null){ try { outputStreamWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
|
序列化 & 反序列化
序列化
将对象转成二进制并保存到磁盘中
对象需要实现序列化接口
反序列化含义
将磁盘中的二进制对象加载到内存中
对象需要实现序列化接口
要求
包名序列化前后也要一样
实现Serializable接口
生成一个版本号
作用:用来校验类是否修改过
案例
User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class User implements Serializable{
private static final long serialVersionUID = -3986195817302832270L; private String name; private Integer num; public User(String name, Integer num) { super(); this.name = name; this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getNum() { return num; } public void setNum(Integer num) { this.num = num; } @Override public String toString() { return "User [name=" + name + ", num=" + num + "]"; } }
|
Test.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| public class Test { public static void main(String[] args) { String target = "C:\\xx.txt";
User result = objectInput(target); System.out.println(result); }
private static void objectOutput(String target,User user) { OutputStream outputStream=null; ObjectOutputStream objectOutputStream=null; try { outputStream = new FileOutputStream(target); objectOutputStream = new ObjectOutputStream(outputStream); objectOutputStream.writeObject(user); } catch (IOException e) { e.printStackTrace(); }finally { if(objectOutputStream!=null){ try { objectOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } private static <T> T objectInput(String path){ ObjectInputStream objectInputStream=null; try { objectInputStream = new ObjectInputStream(new FileInputStream(path)); return (T) objectInputStream.readObject(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }finally { if(objectInputStream!=null){ try { objectInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }
|
打印流
含义
可以输出任何类型的数据
注意点
当打印对象的时候,只是输出了对象.toString()结果。并不是将整个对象输出。
种类
- PrintStream
- PrintWriter [掌握]
案例
User.java
1 2 3 4 5 6 7 8 9 10 11
| public class User {
private String name; public User(String name){ this.name = name; } @Override public String toString() { return "User [name=" + name + "]"; } }
|
PrintTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class PrintTest { public static void main(String[] args) throws IOException { PrintWriter printWriter = new PrintWriter("C:\\result.txt"); User user = new User("zs"); printWriter.print(user); printWriter.print(11); printWriter.close(); } }
|
线程
相关概念
串行
多个事件依次执行
并行
多个事件在同一时刻同时执行
并发
在一段时间内多个事件发生
进程
一个正在运行软件,一个软件对应一个进程
一个进程中至少有个一个线程
线程
是进程中的执行分支(索引)
进程和线程区别
- 每个进程都有独立的内存空间
- 一个进程至少要有一个线程
- 每创建一个线程都有自己的栈、本地方法区、程序计数器【TODO】
如何创建线程
入门案例
示意图
![1659497893768](C:/Users/lsy509/Desktop/%E5%AE%9E%E8%AE%AD%E4%B8%89/test/02javase/Day11/%E7%AC%94%E8%AE%B0/assets/1659497893768.png)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| public class _01Thread { public static void main(String[] args) { Thread firstThread = new FirstThread(); firstThread.start(); for(int i=0;i<20;i++){ System.out.println("Main,i="+i); } } }
class FirstThread extends Thread{ @Override public void run() { for(int i=0;i<20;i++){ System.out.println("FirstThread,i="+i); } } }
|
常见的方法上
Thread.currentThread()
获取当前线程对象
start
启动线程【此时是就绪状态并不是说马上执行该线程的任务,而是需要等待获得cpu运行时】
run
指定线程的任务
getId
获取线程的id
getName
获取线程的名称
setName
设置线程的名称,还可以在构造器中调用父类的super(String threadName)
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| package com.neu.day11._04thread;
public class _02Thread { public static void main(String[] args) {
Thread one = new MyThread("java"); one.start(); Thread two = new MyThread("html"); two.start(); System.out.println("main...."); }
}
class MyThread extends Thread{ private String content; public MyThread(String content){ super("thread:"+content); this.content = content; }
@Override public void run() { System.out.println(this.getName()+"="+this.content); } }
|
示意图
![1659506782288](C:/Users/lsy509/Desktop/%E5%AE%9E%E8%AE%AD%E4%B8%89/test/02javase/Day11/%E7%AC%94%E8%AE%B0/assets/1659506782288.png)
两种方式
区别
- 实现方式可以共享资源,继承不可以共享资源
- 实现方式还可以继承其他类,继承方式不可以再继承其他类了
- 资源共享方式有线程安全问题
案例
继承方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class _01BuyTicket { public static void main(String[] args) { Thread one = new BuyThreader(); Thread two = new BuyThreader(); one.start(); two.start(); }
}
class BuyThreader extends Thread{ private int ticket = 10; @Override public void run() {
while(ticket>0){ System.out.println("当前购买的票是:"+ticket); ticket = ticket - 1; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
|
实现接口方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.neu.day11._05thread;
public class _02BuyTicket { public static void main(String[] args) { Runnable buyer = new Buyer(); Thread one = new Thread(buyer); Thread two = new Thread(buyer); one.start(); two.start(); }
}
class Buyer implements Runnable{
private int ticket=10; @Override public void run() { while(ticket>0){ System.out.println("当前购买的ticket是:"+ticket); ticket--; } } }
|
线程安全
常见概念
线程安全
多线程修改操作同一份资源数据不会错乱
线程不安全 [线程安全问题]
多线程修改操作同一份资源带来的数据错乱。
处理方案
案例一
同步方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package com.neu.day11._06safe;
public class _01BuyTicket { public static void main(String[] args) { Runnable buyer = new Buyer(); Thread one = new Thread(buyer); Thread two = new Thread(buyer); one.start(); two.start(); } }
class Buyer implements Runnable{
private int ticket=10; @Override public void run() { buy(); } private synchronized void buy(){ while(ticket>0){ System.out.println("购买的ticket是:"+ticket); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket--; } } }
|
案例二
验证两个资源的监视对象不一样的时候,当线程1进入监视对象1的资源时,线程2是否可以进入监视对象2的资源?
结论可以
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class _02TestMonitor { public static void main(String[] args) { Runnable buyer = new MyBuyer(); Thread one = new Thread(buyer); Thread two = new Thread(buyer); one.start(); two.start(); } }
class MyBuyer implements Runnable{ private boolean sign=true; @Override public void run() { if(sign){ sign=false; one(); }else{ two(); } } private synchronized void one(){ System.out.println("one...."); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } } private synchronized void two(){ System.out.println("two...."); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } } }
|
案例三
同步代码块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class _03BuyTicket { public static void main(String[] args) { Runnable buyer = new Killer(); Thread one = new Thread(buyer); Thread two = new Thread(buyer); one.start(); two.start(); } }
class Killer implements Runnable{
private int ticket=10; @Override public void run() { buy(); } private void buy(){ System.out.println("hello"); synchronized (this){ while(ticket>0){ System.out.println("购买的ticket是:"+ticket); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } ticket--; } } } }
|
案例四
使用可重入锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class _04BuyApple { public static void main(String[] args) { Runnable buyer = new BuyerApple(); Thread one = new Thread(buyer,"one"); Thread two = new Thread(buyer,"two"); one.start(); two.start(); }
}
class BuyerApple implements Runnable{ private ReentrantLock lock = new ReentrantLock(); private int count=10;
@Override public void run() {
buy(); } private void buy(){ try { lock.lock(); while(count>0){ Thread thread = Thread.currentThread(); System.out.println(thread.getName()+"购买了,苹果编号是:"+count); count--; } } finally { lock.unlock(); } } }
|
单例
含义
某个类在程序运行期间最多只能创建一个对象
方式
懒汉式
步骤
构造器private
对外提供获取实例的方法
注意里面要考虑线程安全的问题
代码
ATM.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class ATM { private static ATM atm; private ATM(){ }
public static ATM getInstance(){ if(atm==null){ synchronized(ATM.class){ if(atm==null){ atm = new ATM(); } } } return atm; } }
|
Test.java
1 2 3 4 5 6 7 8 9 10
| public class Test { public static void main(String[] args) { ATM atmOne = ATM.getInstance(); ATM atmTwo = ATM.getInstance(); System.out.println(atmOne==atmTwo); } }
|
常见方法下
- isAlive
- setPriority
- getPriority
- isInterrupted
- interrupt
判断是否存活
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class _01isAliveTest { public static void main(String[] args) throws InterruptedException { Thread thread = new MyThread(); thread.start(); Thread.sleep(1000); System.out.println(thread.isAlive()); }
}
class MyThread extends Thread{ @Override public void run() { for(int i=0;i<10;i++){ System.out.println(i); } } }
|
线程优先级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class _02PriorityTest { public static void main(String[] args) throws InterruptedException { Thread oneThread = new Thread(){ @Override public void run() { System.out.println("one的优先级是"+this.getPriority()); } }; Thread twoThread = new Thread(){ @Override public void run() { System.out.println("two的优先级是"+this.getPriority()); } }; twoThread.setPriority(Thread.MAX_PRIORITY); oneThread.setPriority(Thread.MIN_PRIORITY); oneThread.start(); twoThread.start(); } }
|
线程中断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class _03InterruptTest { public static void main(String[] args) throws InterruptedException { Thread thread = new NumThread(); thread.start(); Thread.sleep(100); thread.interrupt(); } } class NumThread extends Thread{ @Override public void run() { for(int i=0;i<100;i++){ if(isInterrupted()){ return; } try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i+"是否中断了"+isInterrupted()); } } }
|