线程和进程的区别
进程是资源分配的最小单位,线程是cpu调度的最小单位
线程和进程的由来
串行 -> 批处理 -> 进程 -> 线程
- 初期的计算机智能串行任务,并且需要长时间等待用户输入
- 预先将用户的指令集中成清单,批量串行处理用户指令,仍然无法并发执行
- 进程独占内存空间,保存各自运行状态,相互不干扰且可以互相切换,为并发处理任务提供了可能
- 共享进程的内存资源,相互间切换更快速,支持更细粒度的任务控制,使进程内的子任务得以并发执行
Thread中的start和run方法的区别
调用start() 方法会创建一个新的子线程并启动
run() 方法只是Thead的一个普通方法的调用
start()调用本地方法将会执行到该步骤,可以看到最后调用run()方法
关于是继承Thread还是实现Runnable就不多说了
线程的6个状态
1.新建(New):创建后尚未启动的线程的状态
2.运行(Runnable):包含Running 和 Ready
3.无限期等待(Waiting): 不会被分配CPU执行时间,需要显式被唤醒
--------没有设置Timeout参数的Object.wait()方法
--------没有设置Timeout参数的Thread.join()方法
--------LockSupport.park()方法
--------Thread.sleep()方法
4.期限等待(Timed Waiting): 在一定时间后会由系统自动唤醒
--------设置Timeout参数的Object.wait()方法
--------设置Timeout参数的Thread.join()方法
--------LockSupport.parkNanos()方法
---------LockSupport.parkUntil()方法
阻塞(Blocked):等待获取排他锁
结束(Terminated):已终止线程的状态,线程已经结束执行
线程对内存的操作
这也就是线程安全问题的主要诱因
存在的共享数据
存在多条线程共同操作这些共享数据
解决问题的根本办法:
同一时刻有且只有一个线程在操作共享数据,其他线程必须等到该线程处理完数据后再对共享数据进行操作 (synchronized、volatile)
单例的双重检测实现
public class Singleton(){
//禁止指令重排序
private volatile static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
//第一次检测
if(instance == null){
//同步
synchronized (Singleton.class){
if (instance == null){
//多线程环境下可能会出现问题的地方
instance = new Singleton();
}
}
}
return instance;
}
}