目录
5、ThreadLocal类和InheritableThreadLocal类
线程间通信使线程成为一个整体,提高系统之间的交互性,在提高CPU利用率的同时可以对线程任务进行有效的把控与监督。
1、volatile 关键字
volatile有两大特性,一是可见性,二是有序性,禁止指令重排序。其中可见性就是可以让线程之间进行通信。
以下两个线程会轮流执行
public class VolatileTest {
// 保证可见性和有序性
private static volatile boolean flag = true;
public static void main(String[] args) {
new Thread(new Runnable() { // 线程一
@Override
public void run() {
while (true) {
if (flag) {
System.out.println(Thread.currentThread().getName()+": turn on");
flag = false;
}
}
}
}, "thread-1").start();
new Thread(new Runnable() { // 线程二
@Override
public void run() {
while (true) {
if (!flag) {
System.out.println(Thread.currentThread().getName()+": turn off");
flag = true;
}
}
}
}, "thread-2").start();
}
}
2、等待唤醒(等待通知)机制
(1)wait() 和 notify() 等待唤醒
等待唤醒机制可以基于 wait() 和 notify() 方法来实现,在一个线程内调用该线程锁对象的 wait() 方法, 线程将进入等待队列等待直到被唤醒。
wait()/notify() 方法只能在同步方法或同部块中调用
调用 wait() 方法,线程需要获取该对象的对象级别锁,如果没有持锁,将会抛出IllegalMonitorStateException,执行 wait() 方法后,当前线程立即释放锁
执行 notify() 方法后,当前线程不会立即释放锁,需要等到执行 notify() 方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,此时 wait() 状态所在的线程才可以获取该对象的锁。
public class ThreadTest {
// 对象锁
private static final Object lock = new Object();
public static void main(String[] args) {
new Thread(new Runnable() { // 线程一
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + ":获取锁");
try {
lock.wait(); // 线程进入等待
System.out.println(Thread.currentThread().getName() + ":执行wait()方法结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":执行结束");
}
}
}, "thread-1").start();
new Thread(new Runnable() { // 线程二
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + "获取锁");
lock.notify(); // 唤醒一个线程
System.out.println(Thread.currentThread().getName() + ":执行notify()方法结束");
try {
Thread.sleep(1000);