复习:
线程 :
【执行代码,同时执行多段代码】
【快速】
【不确定】
抢占式调度
前台线程 :
main线程 : 前台线程不停止 jvm不会关闭
后台线程 :
gc : 前台线程全部都销毁,后台线程也会死亡。
新建状态:
1,My1 继承 Thread
My1 t = new My1();
2,My2 实现 Runnable{}
Runnable r = new My2();
Thread t = new Thread(r);
就绪状态:
start();
可以抢占cpu执行权限
运行状态 : 运行run中的代码
阻塞状态:
1,挂起 : 不释放锁资源,不抢夺cpu执行权限
sleep();
Thread.sleep(1000);
join();
t.join();
yield(); 让步 :
2,锁池等待 :
当线程执行有锁的代码时,锁被其他线程获取走了
当前线程就回到锁池等待
其他线程执行完毕加锁的代码,就会自动释放锁。
当前线程从锁池回到就绪状态.
3,等待池等待 :
锁.wait();会释放锁资源,释放cpu执行权限
锁.notifyAll();
回到锁池等待
t.interrupt();
回到锁池等待
死亡状态 : 运行完run中代码
线程安全问题:线程同步
数据安全:
多线程 操作 公同的 数据 会发生数据安全问题。
1,不用共同数据,使用局部变量
2,把处理共同数据的代码,锁起来.
锁对象 需要 唯一
//锁对象? this
public sy void show(){}
//锁对象? 类.class
public static sy void show(){}
线程通信:
线程执行 , 不可控 ,
让线程 执行,停止,暂停。
//立刻停止,不能做相关的备份处理事情
stop();
//打断,设置一个标志位,没有影响线程,
//提示,有了提示信息以后,自己来处理。
//是否要中断当前线程的运行
interrupt();
//获得标志位,不清空
isInterrupted();
//获得标志位,清空
interrupted();
如果代码有锁
wait();//让线程暂停
notifyAll();//唤醒等待状态的线程
8,线程的死锁
A线程需要的锁被B线程获取
B线程需要的锁被A线程获取
9,线程的让步
yield()方法
Thread.yield()静态方法,
如果此时具有相同优先级的其他线程处于就绪状态,那么yield()方法将把当前运行的线程放到可运行池中并使另一个线程运行。如果没有相同优先级的可运行线程,则yield()方法什么也不做。
yield()只会给相同优先级或者更高优先级的线程一个运行的机会。
yield()转到就绪状态;
yield()不抛任何异常
yield()并不常用。
10. 调整线程优先级
注意:优先级高的线程只能获得较多运行的概率,但是实际中不一定真的有效果
线程优先级的使用原则与操作系统有着密切的联系因此在JAVA中的线程的调度是完全受其所运行平台的操作系统的线程调度程序控制的。所有虽然我们可以设置线程的优先级但是在运行的时候不一定能够确切的体现出来。
所有处于就绪状态的线程根据优先级存放在可运行池中,优先级低的线程获得较少的运行机会,优先级高的线程获得较多的运行机会。
Thread类的setPriority(int)和getPriority()方法分别用来设置优先级和读取优先级。
优先级用整数来表示,取值范围是1-10,Thread类有以下3个静态常量。
. MAX_PRIORITY: 10, 最高;
. MIN_PRIORITY: 1, 最低;
. NORM_PRIORITY: 5, 默认优先级;
释放对象的锁:
. 执行完同步代码块;
. 执行同步代码块过程中,遇到异常而导致线程终止,释放锁;
. 执行同步代码块过程中,执行了锁所属对象的wait()方法,释放锁进入对象的等待池;
线程不释放锁:
. Thread.sleep()方法,放弃CPU,进入阻塞状态;
. Thread.yield()方法,放弃CPU,进入就绪状态;
死锁:
package com.briup.ch16;
/**
* 死锁
* */
public class Test5 {
public static final Object a = new Object();
public static final Object b = new Object();
public static void main(String[] args) throws InterruptedException {
My5 my = new My5();
my.start();
synchronized (Test5.b) {
synchronized (Test5.a) {
System.out.println("main核心 代码");
}
}
}
}
class My5 extends Thread{
@Override
public void run() {
synchronized (Test5.a) {
synchronized (Test5.b) {
System.out.println("my核心代码");
}
}
}
}
一,IO流基础概念: 把数据从 数据源 输送到 数据目的地。
1.1:数据可能存在的位置
1.1.1:键盘输入(从控制台输入)
1.1.2:文件读入
1.1.2:java代码中
1.2:主要负责
【输入和输出】
【当前代码】
1.3:输入输出方式:
1.3.1:字节---> 字节流
1.3.2:字符---> 字符流
乱码
1.4: 细分,都是位于 java.io 包里。
1.4.1:字节 输入流 : inputStream
1.4.2:字节 输出流 : outputStream
1.4.3:字符 输入流 : XxxxxReader
1.4.4:字符 输出流 : XxxxxxWriter
注: inputStream 和 outputStream 是抽象类
二,IO流 基础操作:
2.1:输入流 InputStream/Reader
2.1.1: read();会阻塞代码.从输入流读取一个字节(1字节是8位),把它转换为0-255之间的整数,并返回这一整数。如果遇到输入流的结尾,则返回-1;
2.1.2: read(byte[] but);会阻塞代码.从流中读取字节数据,把读取到的字节数据放到数组中,一直放满数组。返回的整数表示读取的字节数。如果遇到输入流的结尾,则返回-1;
2.1.3: read(byte[] b, int off, int len)会阻塞代码.从输入流读取若干个字节,把它们保存到参数b指定的字节数组中。返回的整数表示读取的字节数。参数off指定在字节数组中开始保存数据的起始下标,参数len指定读取的字节数目。返回的整数表示实现读取的字节数。如果遇到输入流的结尾,则返回-1;
注:第二个和第三个效率大于第一个。因为:减少进行物理读文件或键盘的次数,因此能提高I/O操作的效率。
2.1.4: available(): 返回可以从输入流中读取的字节数目;
2.1.5: skip(long): 从输入流中跳过参数n指定数目的字节/字符。
2.1.6: close(): 关闭输入流,
不关闭流,资源被占用,
其他进程不能使用
2.1.7: 字节流 读取到流尾 返回 -1;
2.1.8: 字符流 读取到流尾 返回 null;