复习多线程,首先复习多线程的状态图
首先先复习一下状态:
新建状态(new):线程对象被创建。也就是 Thread thread = new Thread();
就绪状态(runnable):线程执行了start()方法,线程进入就绪状态,此时线程还没有获取的CPU,还
没有执行,只有在就绪状态的线程才能获取CPU。
运行状态(running):运行状态,线程获取了CPU,正在执行该线程,只有就绪状态才能进入运行状态
阻塞状态:正在运行中的线程,因为某种原因暂时放弃对CPU的使用权,停止执行。直到再次进入就绪状态,才能再次获得CPU执行线程
1、 等待阻塞:线程调动了wait()方法,是线程进入阻塞状态
2、 锁定阻塞:线程在获取synchronized同步锁时失败,进入阻塞状态,等待锁释放
3、 其他阻塞:当线程调用sleep()或join()方法,线程进入阻塞状态。
死亡状态:线程正常运行完或者异常退出,线程生命周期结束
现在复习线程常用的方法:
start():开始线程的方法,与调用run方法不同的是,直接调用run等于是同步调用,执行start才是异步
yield():使当前运行中的线程,放弃CPU,进入就绪状态。有时候会发现效果不明显,yeild方法使线程放弃的时间不确定,可能刚放弃有马上获得了CPU。
sleep():使当前线程在指定毫秒数内休眠,放弃CPU进入阻塞状态,休眠结束后,进入就绪状态。
join():当前线程放弃CPU等待其他线程执行结束后(也可以指定等待时间),在进入就绪状态。
wait():释放当前对象锁,并且进入阻塞列
notify():唤醒当前对象阻塞队列中随机一个阻塞线程。
notify():唤醒当前对象阻塞队列中所有的阻塞线程。
Interrupt():其作用是中断该线程,但实际上只是给线程设置一个中断标记,线程仍会运行。
其中wait,notify,notify方法着重复习一下:
这三个方法要与synchronized一起使用,因为我们在使用synchronized需要一把锁,每个对象都有一个与之对应的监视器,监视器里面有该对象的锁,一个等待队列和一个同步队列。Wait方式释放锁,正在拥有该锁的线程线程失去CPU权限,进入等待(阻塞)队列,被wait的线程无法自己唤醒自己,如果没有notify,线程就会一直停在这里等待唤醒,使用notify方法是把该对象锁下等待队列下的一个线程唤醒,进入锁定(同步)队列,并不是把锁直接给它,该线程需要跟其他锁定队列的线程竞争,获得同步锁后的线程,进入就绪状态。
线程实现方式:
1、 继承Thread类 (常见)
2、 实现Runnable接口 (常见)
3、 实现callable接口
4、 通过ExectorService(线程池)实现线程
线程同步的方式:
1、 同步方法
就是用synchronized关键字修饰的方式
2、 同步代码块
用synchronized修饰的代码块
Synchronized(object){
}
3、 使用volatile实现线程同步
4、 使用重入锁实现线程同步
在java5中新增的一个java.util.concurrent来支持同步。ReentrantLock类是可重入,互斥实现了lock接口的锁。
常用方法:
ReentrantLock():创建一个实例
Lock()获得锁
Unlock()释放锁
5、 使用局部变量实现线程同步
6、 使用原子变量实现线程同步
7、 使用阻塞队列实现线程同步