概念
进程:是系统进行资源分配和调度的基本单位。
线程:一个进程里面的不同的执行路径。
java创建线程的几种方式
1.new Thread().start();
2.new Thread(Runnable).start();
3.Executors.newCachedThreadPool()或者FutureTask+Callable
线程常用方法
sleep:睡眠,当前线程暂停一段时间让给别的线程去运行,等睡眠到规定时间自动复活
yield:当前线程正在执行的时候停下来进入等待队列,回到等待队列后在系统的调度算法里还是依然可能把你刚回去的这个线程拿回来继续执行,更大的可能是把原来等待的那些线程拿一个出来执行,所以yield的意思就是我让出一下CPU。
join:在自己当前线程加入你调用join的线程,本线程等到,等调用的线程运行完了,自己再去执行(自己join自己没有意义)。
线程状态
新建状态(new):当new一个线程时,还没有调用start()时处于这个状态
就绪状态(Ready):线程对象调用start()方法时,他会被线程调度器来执行
运行状态(Running):真正扔到CPU上去运行的时候
阻塞状态(Blocked):在同步代码块的情况下没有获取到锁
- TimedWaiting等待:按照时间等待,等待时间介绍就会自己回去。(Thread.sleep(time)、o.wait(time)、t.jion(time)、LockSupport.parkNanos()、LockSupport.parkUntil()这些都是关于时间等待方法)
- Waitting等待:在运行的时候调用o.wait()、t.join()、LockSuppart.park()进入Waitting状态,调用o.notify()、o.notifyAll()、LockSuppart.unPark()就又回到Running状态
结束状态(Teminated):如果线程顺利执行完进入该状态,Teminated完了之后不能再回到new状态。
synchronized
Object o= new Object();
synchronized(o){}
锁定的是o对象
synchronized(this){}
public synchronized void m(){}
锁定当前对象
public class T{
public synchrinized static void m(){}
}
静态方法static是没有当前对象的,这里这个synchronized(T.class)锁的就是T类对象
一个同步方法可以调用另一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁,也就是说synchronized获得锁是可重入的。
程序在执行过程中,如果出现异常,默认情况锁会被释放
synchronized(Object)不能用String,常量 Integer Long
synchronized锁的是对象不是代码
锁升级
HostSpot实现:
偏向锁:当第一个线程访问这个锁的时候(sync(Object)),现在Object的头上markword记录这个线程,如果只有一个线程访问实际上是没有给这个Object加锁的,只是记录这个线程的ID。
自旋锁:如果有其他线程争用的话就会升级为自旋锁,自旋消耗CPU资源。
重量级锁:当自旋十次之后就会升级为重量级锁,重量级锁需要去操作系统申请资源(这个资源是有限的)
执行时间短(加锁代码),线程数少。用自旋锁(CAS)
执行时间长,线程数多,用系统锁(sync)