- 进程和线程有什么区别?
- synchronize 的本质是什么?
- 死锁是什么?
- 乐观锁和悲观锁是什么?
- volatile 关键字有什么作用?
本篇记录Java多线程和线程同步(synchronize),带着问题学习才是最有效的方法。下面会对上述问题由浅入深,进行原理性的讲解,大部分会用最简单的例子讲解到原理。理解了才是自己的知识。
开启线程
先来个最简单的如何开启一个新线程:
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("Thread started!");
}
};
thread.start();
上面的代码就是开启一个线程执行打印。调用一个 thread.start()就能开启一个新线程,在后台执行一个打印操作,那么会不会有疑问,这个是怎么做到开启一个新线程的呢?
来看下 start() 方法
public
class Thread implements Runnable {
...
public synchronized void start() {
...
start0();
...
}
private native void start0();
...
}
可以看到,最终调用了 native 方法。看见 native,如果不是做NDK开发的话就可以停下来了,一个 native 方法就是一个本地方法,是虚拟机跟平台沟通的。
什么叫平台
比如说Java虚拟机是运行在 Android 上就是 Android平台,还有Windows平台,Mac平台等。
Java到这里已经不负责实际的交互了,它只是跟虚拟机去做交互,它告诉虚拟机“我需要什么操作”,虚拟机就会根据具体的平台做出不同的行为。也就是说这个具体行为已经不是Java代码可以控制的了。所以知道这做了什么就好,因为不同平台实际代码也不一样。
本地方法 start() 做了什么
Java告诉虚拟机,开一个新线程,在新线程里面执行 run() 方法,那么这个 run() 方法是怎么切换到另一个线程来执行的呢?它是虚拟机去指挥操作系统来做的,不同的操作系统它们的切换方式是不一样的。Java本身是没有切换线程的能力的,它都是需要交给虚拟机,虚拟机再交给系统来做的,一个语言是没办法切线程的,它只是一级一级的去指挥。
new Runnable() 和 new Thread() 区别
顺带提一下,这两个可能都是常用的方法,有没有想过这两个有什么区别。先来看下 Runnable 怎么用:
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Thread with Runnable started!");
}
};
Thread thread = new Thread(runnable);
thread.start
看下源码:
public
class Thread implements Runnable {
...
/* What will be run. */
private Runnable target;
...
private void init(ThreadGroup g, Runnable target