Java 线程通信方法
0、(why) 每个线程都有自己的栈空间,我们要线程之间进行交流,合作共赢。
1、synchronized 和 volatile 关键字
a) 看下面的 synchronized 关键字
b) 看下面的 volatile 关键字
2、等待 / 通知机制:一个线程 A 调用对象的 wait()方法,另一个线程调用线程 B 的 notity()或者的 notifyall()方法.
a) 顺序打印奇数偶数
public class ThreadPrintDemo2 {
public static void main(String[] args) {
final ThreadPrintDemo2 demo2 = new ThreadPrintDemo2();
//java8 新特性
Thread t1 = new Thread(demo2 :: print1);
Thread t2 = new Thread(demo2 :: print2);
t1.start();
t2.start();
}
public synchronized void print2() {
for (int i = 1; i <= 100; i +=2) {
System.out.println(i);
this.notify(); // 通知等待中的进程
try {
this.wait(); // 线程进入等待
Thread.sleep(100);// 防止打印速度过快导致混乱
} catch (InterruptedException e) {
// NO
}
}
}
public synchronized void print1() {
for (int i = 0; i <= 100; i += 2) {
System.out.println(i);
this.notify(); // 通知等待中的进程
try {
this.wait(); // 线程进入等待
Thread.sleep(100);// 防止打印速度过快导致混乱
} catch (InterruptedException e) {
// NO
}
}
}
}
b) 打印连续句子
public class ThreadPrintDemo2 {
private char[] arr = new char[]{‘a’, ‘ ‘, ‘b’, ‘c’, ‘d’, ‘e’};
public static void main(String[] args) {
final ThreadPrintDemo2 demo2 = new ThreadPrintDemo2();
Thread t1 = new Thread(demo2::print1);
Thread t2 = new Thread(demo2::print2);
t1.start();
t2.start();
}
public synchronized void print2() {
for (int i = 1; i < arr.length; i +=2) {
System.out.print(arr[i]);
this.notify();
try {
this.wait();
Thread.sleep(100);// 防止打印速度过快导致混乱
} catch (InterruptedException e) {
// NO
}
}
}
public synchronized void print1() {
for (int i = 0; i < arr.length; i +=2) {
System.out.print(arr[i]);
this.notify();
try {
this.wait();
Thread.sleep(100);// 防止打印速度过快导致混乱
} catch (InterruptedException e) {
// NO
}
}
}
}
结果:a bcde3、管道输入输出流:pipedreader 和 pipedwriter 面向字符
Pipedoutputstream 和 pipedinputstream 面向字节
4、使用 thread.join() 方法:利用线程等待特性
5、使用 ThreadLocal 线程变量
Synchronize 关键字(重量级锁)
1、基础:Java 中每一个对象都可以作为锁
2、手段:确保多线程在同一时刻,只有一个线程处于方法或同步块中
3、实现原理:JVM 基于进入和退出 monitor 对象来实现方法同步和代码块同步
4、锁优化:jdk1.6 之后优化了锁,加入了偏向锁和轻量级锁,锁可以升级但不能降级
5、使用场景:方法 代码块
Lock 接口
1、他是一个接口
2、使用的时候需要显式获取锁
3、使用方法:
Lock lock = new ReentrantLock();
lock.lock();
try {
}finally {
lock.unlock();
}
4、Synchronized 经常与 Lock 放在一起比较
Volatile
1、是什么:(what)是轻且量级的 synchronize,保证共享变量的可见性(一个线程修改一个共享变量的时候,另一个线程会知道),并他不会引起线程的上下文切换和调度。
2、使用场景:修饰变量
3、优化:在 1.7 中将共享变量追加了 60 个字节,变成 64 个字节。因为(硬件)目前流行的 cpu 的高速缓存行是 64 个字节,当队列的头尾节点不足 64 字节时候,处理器会将他们读到同一个缓存行,并且锁定缓存行。这样会影响队列出队入队效率。
ThreadLoacl 类(线程变量)
为每个线程变量创建一个该变量的副本,避免并发访问的线程安全问题,保证线程安全