线程:
前台线程:
1.线程执行main–>main线程
2.只要有前台现在在执行,jvm就不会停。
后台线程(守护线程/精灵线程):
当 前台线程 结束 守护线程也会结束。
线程生命周期:
新建状态:
继承Thread类,重写run方法,得到新线程
就绪状态:
线程调用.start()方法,进入就绪状态。
运行状态:
线程获得cpu时间片,执行代码,线程进入运行状态
阻塞状态:
代码暂停运行;
1.挂起:sleep(ms);join();yield(),
恢复为就绪状态:
sleep():睡觉时间完了
join();目标线程执行完毕
yield();让出cup执行权限立刻回到就绪状态
注: 不会释放锁资源
2.锁池等待:在run方法中执行了加锁的代码,但是锁被其他线程获取走了,当前线程就会到锁池等待.
恢复为就绪状态:
当其他线程释放锁资源,立刻回到就绪状态
3.等待池等待:当执行wait()方法以后就会到等待池等待
恢复为锁池等待:
当其他线程执行了notify/notifyall方法的时候回从等待池回到锁池等待.
注: wait()方法会释放锁资源
死亡状态:线程执行完run方法中所有代码,或者调用.stop()方法,或jvm强制停止。
线程同步:synchronized
线程不安全:多个线程操作同一份数据就会导致线程不安全问题
线程同步就是解决这个问题的,通过加锁就可以达到线程同步
1:synchronized关键字可以出现的地方【代码块里,静态代码块不行】
2:synchronized(锁){//线程同步的代码}
3:public synchronized void say(){}-->this
4:public static synchronized void say(){}-->Hello.class
注意问题: 多个线程对象使用的锁是不是同一把锁
是,多个线程 对于 锁 上的代码按顺序运行
否, 多个线程 对于 锁 上的代码任意运行
JMM关于synchronized的两条规定:
线程解锁前,必须把共享变量的最新值刷新到主内存中
线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从内存中重新读取最新的值(注意:加锁与解锁需要是同一把锁)
线程解锁前对共享变量的修改在下棋甲所示对其他线程可见
线程同步:
使用 锁对象.wait(); 会释放锁资源 放弃cup执行权限
锁对象.notify();
锁对象.notifyAll();
线程死锁:
yield()方法
Thread.yield()静态方法,
如果此时具有相同优先级的其他线程处于就绪状态,那么yield()方法将把当前运行的线程放到可运行池中并使另一个线程运行。
如果没有相同优先级的可运行线程,则yield()方法什么也不做。
yield()只会给相同优先级或者更高优先级的线程一个运行的机会。
yield()转到就绪状态;
yield()不抛任何异常
yield()并不常用。
调整线程优先级:
注意: 优先级高的线程只能获得较多运行的概率,但是实际中不一定真的有效果Thread类的setPriority(int)和getPriority()方法分别用来设置优先级和读取优先级。优先级用整数来表示,取值范围是1-10,Thread类有以下3个静态常量。
. MAX_PRIORITY: 10, 最高;
. MIN_PRIORITY: 1, 最低;
. NORM_PRIORITY: 5, 默认优先级;