本文最后更新于 2024-11-30 17:14:04
1、IO
本节的输入输出是相对于运行的java文件
1.字节流
FileInputStream
: 字节输入流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| FileInputStream stream=new FileInputStream('文件路径');
stream.read();
byte[] bytes=new byte[3]; stream.read(bytes);
|
FileOutputStream
: 字节输出流
1 2 3 4 5 6 7 8 9
| FileOutputStream stream=new FileOutputStream('文件路径');
stream.write('a'); stream.write('a'.getBytes()); stream.write('abcde'.getBytes(),2,1); stream.flush();
|
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("test.txt"); FileOutputStream fos = new FileOutputStream("test_copy.txt")) {
byte[] buffer = new byte[1024]; int len = 0; while ((len = fis.read(buffer)) != -1) { fos.write(buffer, 0, len); } } catch (IOException e) {
e.printStackTrace(); } }
|
2.字符流
FileReader
:输入
1 2 3
| FileReader reader=new FileReader('文件路径');
reader.read();
|
FileWriter
: 输出
1 2 3 4 5 6 7 8 9 10 11 12
| FileWriter writer=new FileWriter('路径');
writer.append('a') .append("adfad");
|
字符流只支持char[]
类型作为存储
3.文件对象
File
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| File file=new File('路径文件 / 文件夹名字');
file.mkdir() file.mkdirs()
file.createNewFile();
|
4.缓冲流
BufferedInputStream
:
BufferedOutputStream
:
1 2
| BufferedInputStream buff=new BufferedInputStream(new FileInputStream("test_copy.txt"),index);
|
认为:自来水 ===> 自来水厂 ===> 用户
5.转换流
InputStreamReader
: 可以使用 Reader
的方式读取
OutputStreamWriter
: 可以使用writer
的方式写入
1 2
| OutputStreamWriter writer=new OutputStreamWriter(new FileOutputStream("test_copy.txt"),"UTF-8"); InputStreamReader reader=new InputStreamReader(buff,"UTF-8");
|
6.打印流
PrintStream
:
·Scanner·
用法和上述几种大同小异
所用的sout
(简写)也是这种类型
7.数据流
DataInputStream
DataOutputStream
8.对象流
ObjectOutputStream
不仅支持基本数据类型,而且通过对对象的序列化操作,以某种格式保存对象,来支持对象类型的 IO ,注意:他不是继承FilterInputStream
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
| public class Main { public static void main(String[] args) { try(ObjectOutputStream ois = new ObjectOutputStream(new FileOutputStream("person.text")); ObjectInputStream ois2 = new ObjectInputStream(new FileInputStream("person.text"))){ Person p1 = new Person("Alice"); Person p2 = new Person("Bob");
ois.writeObject(p1); ois.writeObject(p2); Object object ; try { while((object = ois2.readObject())!= null) { System.out.println(object); } }catch (EOFException e){ System.out.println("EOF"); } } catch (IOException | ClassNotFoundException e) { throw new RuntimeException(e); } } static class Person implements Serializable { private static final long serialVersionUID = 1; private String name; Person(String name) { this.name =name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } }
|
2.多线程
进程含有多个线程
注意:是并发操作,不是并行
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public static void main(String[] args) { Thread t = new Thread(new Runnable() { @Override public void run() { System.out.println("子线程"); System.out.println("Hello World"); } }); t.start(); System.out.println("主线程"); }
|
也可使用 lambda 表达式
1 2 3 4 5 6 7 8
| public static void main(String[] args) { Thread t = new Thread(() -> { System.out.println("子线程"); System.out.println("Hello World"); },"线程名字"); t.start(); System.out.println("主线程"); }
|

1.线程休眠和中断、优先级
Thread.interrupt();
: 使线程中断
Thread.interrupted();
:使线程中断回复原来的状态(即:不中断)
.yield()
:线程的让位,尽可能执行其他的
.join()
: 线程的加入,先执其行他的
当 i==3
之后,尽可能执行 t1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static void main(String[] args) { Thread t = new Thread(() -> { System.out.println("线程 t 启动"); for (int i = 0; i < 10; i++) { System.out.println("线程t "+i); if(i==3) Thread.yield(); } }); Thread t1 = new Thread(() -> { System.out.println("线程 t1 启动"); for (int i = 0; i < 10; i++) { System.out.println("线程t1 "+i); } });
t.start(); t1.start(); }
|
同时开始,但是当 t1 中 i == 5
的时候,只执行 t ,t 结束后才执行 t1
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 static void main(String[] args) { Thread t = new Thread(() -> { System.out.println("线程 t 启动"); for (int i = 0; i < 100; i++) { System.out.println("线程t "+i);
} System.out.println("线程 t 结束"); }); Thread t1 = new Thread(() -> { System.out.println("线程 t1 启动"); for (int i = 0; i < 10; i++) { System.out.println("线程t1 "+i); if (i == 5) {{ try { System.out.println("线程 t1 等待 t 结束"); t.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } }} } System.out.println("线程 t1 结束"); });
t.start(); t1.start(); }
|
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
| private static int p = 0;
public static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> {
for (int i = 0; i < 10000; i++) { p++; } }); Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) { p++; } }); t.start(); t1.start(); Thread.sleep(1000); System.out.println(p); }
|
高速缓存通过保存内存中数据的副本来提供更加快速的数据访问,但是如果多个处理器的运算任务都涉及同一块内存区域,就可能导致各自的高速缓存数据不一致,在写回主内存时就会发生冲突,这就是引入高速缓存引发的新问题,称之为:缓存一致性。
synchronized
该关键字,可以通过给变量,或者方法加锁,使得不能同时操作同一个方法或者变量
例如:
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
| private static int p = 0;
private static synchronized void add() { p++; }
public static void main(String[] args) throws InterruptedException {
Object lock = new Object(); Thread t = new Thread(() -> {
for (int i = 0; i < 10000; i++) { synchronized (lock) { p++; } } }); Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) { synchronized (lock) { p++; } } }); t.start(); t1.start(); Thread.sleep(100); System.out.println(p); }
|
3.死锁
两个线程互相卡锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
jps jstack processID
jconsloe
|
.wait()
: 使当前进程进入等待,同时释放当前的锁,可以让其他进程获取
可输入一个形参变量,用于设置最大等待时间 单位 ms
.notify()
: 唤醒刚才等待的进程(此时并没有立即释放锁),等待当前进程结束,才会执行刚才等待的进程
.notifyAll()
: 释放所有等待的进程,上面的为随机选取一个释放
例子:
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
| private static int p = 0;
private static synchronized void add() { p++; }
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread t = new Thread(() -> { synchronized (lock) { System.out.println("进程1开始"); try { lock.wait(); System.out.println("进程1结束"); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); Thread t1 = new Thread(() -> { synchronized (lock) { lock.notify(); try { System.out.println("进程2开始"); Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("进程2结束");
} });
t.start(); t1.start(); }
|
4.定时任务
Timer
5. 守护进程
在主进程结束的时候,子线程也结束。
如果不使用的话,当主进程结束后,子进程没有结束的条件下,该进程仍然在执行
守护进程必须在进程开始之前!!!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread t = new Thread(() -> { while(true){ System.out.println("我是守护线程"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); t.setDaemon(true); Thread.sleep(3000); t.start(); }
|
6.生产者和消费者
大概就是使用线程来进行操作,设置一个死循环用于不断地执行。
不妨令A、B分别为生产者和消费者
则A、B分别开启一个线程,并不断执行,当A生产出东西的时候,B才可以调用,其他时间一直等待,具体的可以参考下面的例子(仅供参考,考虑可能真的不够周全!!!)
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
| public class Main { private static Queue<Object> queue=new LinkedList<>();
public static void main(String[] args) throws InterruptedException {
new Thread(Main::add,"add-thread-1").start(); new Thread(Main::add,"add-thread-2").start();
new Thread(Main::take,"take-thread-1").start(); new Thread(Main::take,"take-thread-2").start();
}
public static void add(){ while(true){ try { Thread.sleep(1000); synchronized (queue){ String name=Thread.currentThread().getName(); System.out.println(new Date().toString()+" "+name+" add "); queue.offer(new Object()); queue.notifyAll(); } } catch (InterruptedException e) { throw new RuntimeException(e); } }
}
public static void take(){ while(true){ try { synchronized (queue){ while(queue.isEmpty()) queue.wait(); String name=Thread.currentThread().getName(); Object obj=queue.poll(); System.out.println(new Date().toString()+" "+name+" take "+obj); } } catch (InterruptedException e) { throw new RuntimeException(e); } } }
}
|