1.Java程序的运行原理
由java命令启动JVM,JVM启动就相当于启动了一个进程。
接着有该进程创建了一个主线程去调用main方法。
2.jvm虚拟机的启动是单线程的还是多线程的?
多线程的。
原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。
现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的。
3.run()和start()的区别?
run()
:仅仅是封装被线程执行的代码,直接调用是普通方法
start()
:首先启动了线程,然后再由jvm去调用该线程的run()方法。
4.实现多线程的两种方式
推荐使用Runnable接口:
- 可以避免由于Java单继承带来的局限性,支持多实现。
- 适合多个相同程序去处理同一个资源的情况,把线程同程序的代码、数据有效分离,较好地体现了面对对象的设计思想。
5. 多线程安全的判断依据
- 是否有多线程环境
- 是否有共享数据
- 是否有多条语句操作共享数据
6. 同步解决线程安全问题
(1)同步代码块
这里的锁对象可以是任意对象。
@Override
public void run() {
//创建锁对象
private Object obj = new Object();// 可以是任意类的对象
synchronized(obj ) {
需要被同步的代码;
...
}
}
(2)同步方法
把同步加在方法上。这里的锁对象是this
public void run() {
method1();//调用同步方法
}
// 定义同步方法
private synchronized void method1() {
...
}
(3)静态同步方法
把同步加在方法上。
这里的锁对象是当前类的字节码文件对象。
private static synchronized void method1() {
...
}
7.线程安全的集合
线程安全的集合包括:StringBuffer
、Vector
、Hashtable
用Collections工具类的方法可以把一个线程不安全的集合类变成一个线程安全的集合类。
8.Lock
是一个接口,是一种更方便实现同步的方式
* Lock:
* void lock(): 获取锁。
* void unlock():释放锁。
* ReentrantLock是Lock的实现类.
try {
lock.lock(); // 加锁
同步内容...
} finally {
lock.unlock(); // 释放锁
}