目录
一、线程基本概念
二、线程间安全竞争统一资源机制:synchronized
三、线程间的基本协作机制:wait/notify
四、取消\关闭线程机制:中断
-------------------------------------------------------------------------------------------------------------------------------------------------
一、线程基本概念
1、创建线程
线程是一条单独的执行流,有自己的程序计数器和栈。
2、创建线程的两种方式:
- 继承Thread(java.lang.Thread这个类表示线程),重写run()
- 实现Runnable接口,重写run()
注:1)两者启动线程都需要创建一个Thread对象,并使用start()方法来启动。
2)start()表示启动该线程,使其成为一条单独的执行流,操作系统会分配线程相关的资源,每个线程会有单独的程序执行计数器和栈,操作系统会把这个线程作为一个独立的个体进行调度,分配时间片让他执行,执行的起点是run()。
3)如果不用start(),用run(),则run()的代码仍然在main线程中执行。
3、线程基本属性和方法
1)id和name
2) 优先级
3) 状态
Thread有一个方法获取线程的状态:public State getState() 返回的State是一个枚举类
public enum State{
NEW, 没有调用start的线程
RUNNABLE, 线程正在运行(并不是指CPU刚刚好在运行此线程)
BLOCKED, 被堵塞
WAITING, 等待
TIMED_WAITING,等待
TERMINATED; 线程运行结束 }
4)是否daemon线程(辅助线程)
当程序中只有daemon线程时就会退出。
5)sleep方法
public static native void sleep(long millis) throws InterruptedException
6)yield方法
告诉操作系统的调度器让出时间,但操作系统不一定会听
7)join方法
可以保证main线程在子线程结束后在退出。
4、共享内存及可能存在的问题
当出现以下两种情况时,不同线程访问操作相同的代码会出现问题:
1)竞态条件
当代码中的操作不是原子操作,例如count++,在执行过程中有其他线程插入,会导致最后的count总数不准确。
解决方法:
- 使用synchronized关键字
- 使用显式锁
- 使用原子变量
2)内存可见性
一个线程对内存的修改,另一个线程看不到,一是修改没有及时同步到内存,而是另一个线程根本没从内存读。(可能在缓存中修改了但未来得及修改到内存中)
解决方法:
- 使用volatile关键字
- 使用synchronized关键字或显式锁同步
二、线程间安全竞争统一资源机制:synchronized
同步机制有synchronized与Lock两种锁方式
synchronized锁
1)使用synchronized加在方法上时,会获取该对象的锁。如果该锁被其他线程占用,则当前线程会等待,当synchronized方法正常返回或者抛异常而终止,jvm会自动释放对象锁。方式为以下两种:
public synchronized void get(){
//执行逻辑
}
public void get(){
synchronized(this){
//执行逻辑
}
}
2)使用synchronized加在静态方法\代码块上时,会获取该类的锁。类锁是用来控制静态方法(或静态变量)之间的同步的。
public static synchronized void get(){
//执行逻辑
}
public void get(){
synchronized(SynchronizedDemo.class){
//执行逻辑
}
}