前言:java中有6大状态来分别表示线程的运行情况,从源码中的注释和实例解释如下
- NEW 线程创建没有执行 start()方法
- RUNNABLE 线程执行start()方法进入该状态
- WAITING 线程调用wait() join() 方法都会进入此状态
- BLOCKED 等待监视器锁而被阻塞的线程的线程状态。 一个处于阻塞状态的线程正在等待监视器锁。一旦这个锁被其他线程释放开了 它就进去执行了 变成了RNNABLE状态 不占用CPU
- TIMED_WAITING 一个指定等待时间的等待线程的线程状态。线程由于调用了以下方法中的一个方法,且等待时间为正数,处于定时等待状态.wait(x) join(x)执行后会是这样的状态,当定时等待的时间到了 它会自动恢复到执行。(下面对wait的测试可以说明这点)
- TERMINATED 终止状态 线程运行完了run方法
贴一张盗来的图啊:
上面是对六大状态的总结,下面说一说如何理解锁机制
锁机制就像一个公共车位,来往的车很多,你先使用了这个车位,别人就不能来停车了,除非你把车开走了。锁机制也像这样,你获得了锁,这个锁下面的代码会被当前你的线程私有执行,别的线程只能干瞪眼,除非你执行完了,释放了锁。
synchronized是一个隐式锁,执行完它锁定的内容后(也就是它花括号部分),会自动释放锁。其他等待的线程就可以进来执行了。
在六大状态的wait join wait(x) join(x)值得深度推敲
先看下面例子:
public class MyTest {
public static void main(String[] args) {
Obj obj = new Obj();
obj.i=1;
new Thread(new MyRunnable(obj),"my").start();
}
}
class MyRunnable implements Runnable{
Obj obj;
MyRunnable(){
}
MyRunnable(Obj obj){
this.obj=obj;
}
@Override
public void run() {
while(true){
try {
obj.addI(Thread.currentThread());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(obj.i);
}
}
}
class Obj{
int i = 0;
synchronized public int getI() {
return i;
}
synchronized public void addI(Thread t) throws InterruptedException {
i=i+1;
if(i==5){
System.out.println("执行wait(x)方法,看等待");
wait(10);
System.out.println("wait(x)方法,等待结束");
}
if(i==10){
System.out.println("执行wait()方法,看等待");
//wait();
wait(0);
System.out.println("wait()方法,等待结束");
}
}
}
结果
2
3
4
执行wait(x)方法,看等待
wait(x)方法,等待结束
5
6
7
8
9
执行wait()方法,看等待
可以看出 wait(x)这个方法会等待时间到了 继续执行 而wait(0)是继续等待下去,为什么测试wait(0)因为 wait()方法就是调用的wait(0)
接下来我们看join方法的源码
从源码中可以看出 join()直接调用了 wait()方法(wait()方法是调用了wait(0)的)以为着我们当前的线程会进入等待状态,而t1.join() t1线程就好像优先于当前线程执行了,但是我们t1线程执行完 当前线程还是等待的需要激活。
然而对于join(x) 从源码中可以看出它走的是while(isAlive))下面的wait(x)方法,如果一个线程执行中出现了t1.join() 那么当前线程会进入等待状态,t1线程获得了当前的锁,执行,等待时间一到,t1和当前线程就并发的处理任务了,不需要激活
上面两个结论可以从我们最上面wait() wait(x)的测试中得出,因为join归根结底还是调用了wait()wait(x)的方法。怎么理解t1会看起来优先的执行了 再看我们上面的测试用例,上面 wait(x)期间 当前线程处于waiting状态 让出了锁,如果这时候其他线程正在阻塞,那么他就会执行起来,wait(x)的时间一到 他们就并发了起来