Runnable 存在的意义 及 Volatile关键字的主要作用
前言:
平时我们在使用多线程时,常用的方法会有以下三种:
- 继承 Thread
- 实现 Runnable
- 实现Callable
翻开 Thread 源码:
public
class Thread implements Runnable {
/* Make sure registerNatives is the first thing <clinit> does. */
private static native void registerNatives();
static {
registerNatives();
}
private volatile String name;
private int priority;
private Thread threadQ;
private long eetop;
.../
问: Thread 已经 实现了Runnable 接口,我们直接去实现Runnable又有什么用呢?
**答:**将可执行的逻辑单元和线程控制-分离
包袱已经抛出来了,现在我们看看,如何打开这个包袱,探探究竟。
解惑
背景:银行有3个窗口受理相同的业务,客户拿着排队机生成的号码进行等待处理。
传统方式:
public class Bank {
private final static int max = 50;
public static void main(String[] args) {
Thread thread1 = new TicketWindow("一号窗口");
thread1.start();
Thread thread2 = new TicketWindow("二号窗口");
thread2.start();
Thread thread3 = new TicketWindow("三号窗口");
thread3.start();
}
}
public class TicketWindow extends Thread {
private int max = 50;
private static volatile int index = 1;
private String name;
public TicketWindow(String string) {
this.name = string;
}
@Override
public void run() {
while (index <= max) {
System.out.println("柜台 " + name + "当前的号码是: " + index++);
}
}
}
Runnable 方式:
public class Bank2 {
private final static int max = 50;
private static volatile int index = 1;
public static void main(String[] args) {
/**
* 此处为可执行的逻辑单元
*/
Runnable ticketWindow = () -> {
while (index <= max)
System.out.println("柜台 " + Thread.currentThread().getName() + "当前的号码是: " + index++);
try {
Thread.sleep(100l);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
/**
* 此处为线程的控制
*/
Thread thread1 = new Thread(ticketWindow, "一号窗口");
Thread thread2 = new Thread(ticketWindow, "二号窗口");
Thread thread3 = new Thread(ticketWindow, "三号窗口");
thread1.start();
thread2.start();
thread3.start();
}
}
可以很明显的看出,将可执行逻辑单元与线程的控制进行了分离。
Volatile 关键字的主要作用:
- 强制对缓存的修改操作立刻写入主存
- 如果是写操作,会导致其它的CPU中的缓存失效
- 保证重排序指令的有序