线程通信
线程通信的三种方法:
(1)wait:当前线程释放锁,进入等待状态
(2)notify:当前锁释放,唤醒其它线程对当前资源进行获取
(3)notifyAll:唤醒所有线程
——如果只是wait不去进行notify,该线程资源就会一直进行等待
线程状态
public static void main(String[] args) {
//新建状态,只是线程对象,没有线程特征
Thread.State aNew = Thread.State.NEW;
//可运行状态 - 运行结果便是剩余的四种状态
Thread.State runnable = Thread.State.RUNNABLE;
//被阻塞状态 - 没有获取到锁 - 还在排队中
Thread.State blocked = Thread.State.BLOCKED;
//sleep或者waiting对应时间,进入计时等待 - 其中sleep时候锁未释放,而waiting的时候锁已经释放
Thread.State timedWaiting = Thread.State.TIMED_WAITING;
//直接进入wait等待,未进行notify则会一直wait
Thread.State waiting = Thread.State.WAITING;
//终止状态 - 线程运行完毕
Thread.State terminated = Thread.State.TERMINATED;
}
线程不可见行
1、首先去进行场景引入吧
public class VolatileDem_one extends Thread {
private boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(1100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程对flag进行修改,且修改为true");
flag = true;
}
public static void main(String[] args) {
VolatileDem_one volatileDem_one = new VolatileDem_one();
volatileDem_one.start();
while (true) {
//此时这段已经执行完成,子线程对其进行修改,但未知会到主线程 —— 进程间不可知性 - 一直在读取
if (volatileDem_one.flag) {
System.out.println("flag已修改");
}
}
}
}
主线程会提示flag已修改吗?不会的,子线程的修改在自己的工作空间内,主线程不会主动的去从子线程种获取该对象,除非中间有对应的机制进行同步操作——这个就是线程间变量的不可见性,不可见性的具体原因有以下几点:
* 每个线程都有自己的工作内存,线程都是从主内存拷贝共享变量的副本值 * 每个线程是在自己的工作内存中操作共享变量的
2、如何保证线程变量之间的可知性?这块有两种方式
(1)获取该资源的时候进行加锁,加锁之前会先对工作空间内存进行清空,从主内存中去获取动态变化的值,变化之后的资源便会同步到自己的工作空间中,在锁释放后,本身的变更也会同步到主线程中——是一种被动的方式
public class VolatileDem_two extends Thread {
private boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(1100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程对flag进行修改,且修改为true");
flag = true;
}
public static void main(String[] args) {
VolatileDem_two volatileDem_two = new VolatileDem_two();
volatileDem_two.start();
while (true) {
//此时这段已经执行完成,子线程对其进行修改,但未知会到主线程 —— 进程间不可知性 - 一直在读取
synchronized (VolatileDem_two.class) {
if (volatileDem_two.flag) {
System.out.println("flag已修改");
}
}
}
}
}
(2)使用volatile关键字对变量进行修改
当volatile修饰的变量发生修改时,主内存中对应的变量的值也会同步发生修改,主内存会向使用该变量的线程发送资源变更事件,其它线程回去主动从主内存空间中去进行读值——相对于锁,这是一种主动的方式
public class VolatileDem_three extends Thread {
private volatile boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(1100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程对flag进行修改,且修改为true");
flag = true;
}
public static void main(String[] args) {
VolatileDem_three volatileDem_three = new VolatileDem_three();
volatileDem_three.start();
while (true) {
//此时这段已经执行完成,子线程对其进行修改,但未知会到主线程 —— 进程间不可知性 - 一直在读取
if (volatileDem_three.flag) {
System.out.println("flag已修改");
}
}
}
}