1.概述线程的生命周期
新建状态(new):当线程对象创建后,进入新建状态;
就绪状态(Runnable):当调用线程对象的Start()方法,线程即进入就绪状态。处于就绪状态的线程
只能说线程随时等待cpu调用执行,并不是说会立即执行
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,
直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。
当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
2.概述volatile关键字的含义以及如何使用
1)volatile是Java提供的一种轻量级的同步机制。
2)但是volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。
三大特性:
原子性:即一个操作或者多个操作的执行过程种不会被其它因素打断。
原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作
可见性:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
有序性:程序执行的顺序按照代码的先后顺序执行。
3.synchronized和Lock之间的区别
1).synchronized是关键字,Lock是接口;
2).Synchronized在线程发生异常时会自动释放锁,因此不会发生异常死锁。
Lock异常时不会自动释放锁,所以需要在finally中实现释放锁。
3).Lock提供了更多的实现方法,而且 可响应中断、可定时,
而synchronized 关键字不能响应中断;
4).synchronized关键字是非公平锁,即,不能保证等待锁的那些线程们的顺序,
而Lock的子类ReentrantLock默认是非公平锁,但是可通过一个布尔参数的构造方法实例化出一个公平锁;
5).synchronized无法判断,是否已经获取到锁,而Lock通过tryLock()方法可以判断,是否已获取到锁;
6).Lock可以通过分别定义读写锁提高多个线程读操作的效率。
7).synchronized 少量同步,Lock大量同步;
4.synchronized实现原理
执行线程将先持有monitor, 然后再执行方法,最后再方法完成时释放monitor。
在方法执行期间,执行线程持有了monitor,其他任何线程都无法再获得同一个monitor。
每一个锁都对应一个monitor对象,在HotSpot虚拟机中它是由ObjectMonitor实现的(C++实现)。
每个对象都存在着一个monitor与之关联,对象与其monitor之间的关系有存在多种实现方式,
如monitor可以与对象一起创建销毁或当线程试图获取对象锁时自动生成,但当一个monitor被某个线程持有后,它便处于锁定状态。
5.是否可以直接调用线程对象的run方法,为什么?
当调用start()方法时你将创建新的线程,并且执行在run()方法里的代码。但如果直接调用run()方法,
它不会创建新的线程也不会执行调用线程的代码。
6.wait和sleep的区别
1).sleep来自于Thread类的一个静态方法,wait来自Object类
2).sleep不会释放锁,wait会释放锁
3).sleep到时间会自动恢复,wait必须使用notify或者notifyall进行唤醒;