浅谈线程状态

  • 线程状态

浅谈线程状态_第1张图片
线程状态转换

java的线程一共有五种状态,分别为new(新建), runnable(就绪),running(执行),blocked(阻塞),dead(死亡)

new
新建状态:当我们new Thread()完一个线程之后,它就处于新建状态了。

runnable
就绪状态:当我们start()一个线程的时候,他就处于一个就绪状态,然后等待cpu的时间片。

running
运行状态:当就绪状态的线程分配到了cpu时间片(执行线程的代码)的时候,他就处于运行状态。

blocked
BLOCKED : 阻塞状态,当线程竞争锁失败的时候会处于这种状态

       //t1,t2锁同一个对象,t1启动后t2才启动,保证t1的run代码在t2之前先执行,t1执行后休眠1000s,线程休眠不释放锁,保证t2一定处于阻塞状态,我们用jvisualvm查看线程状态
       Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a){
                    System.out.println("--->"+ Thread.currentThread().getName());
                    try {
                        Thread.sleep(100000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a){
                    System.out.println("--->"+ Thread.currentThread().getName());
                }
            }
        });
        t1.start();
        Thread.sleep(1000);
        t2.start();
        Thread.sleep(100000);

"Thread-0" #13 prio=5 os_prio=0 tid=0x000000001d7e2000 nid=0x4300 waiting on condition [0x000000001e58f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)

"Thread-1" #14 prio=5 os_prio=0 tid=0x000000001d7ce800 nid=0x11b4 waiting for monitor entry [0x000000001e68f000]
java.lang.Thread.State: BLOCKED (on object monitor)

t1对应Thread-0;t2对应Thread-1,t1处于timed_watting状态,t2处于blocked状态,是因为他因为竞争不到锁.

TIMED_WAITING: 等待一段时间;当调用wait(time),Thread.sleep(time),线程会处于这种状态
上面的例子中t1之所以TIMED_WAITTING,是因为t1执行了Thread.sleep(int time)的方法,实际上wait(int time)也会使线程处于这种状态.

WAITING : 等待状态,当调用wait()方法的时候会处于这种状态

dead
死亡状态,当线程执行完毕处于这种状态

  • wait()/notify()/notifyAll()

wait()/notify()/notifyAll()这三个都是object的内置方法,他只能在监视器(synchronized)内使用,作用的是该监视器相关的线程.当他们运行在监视器外面的时候会报错.


浅谈线程状态_第2张图片
监视器

该图是Java的监视器结构图(synchronized实际就是通过监视器来实现同步的),它由三部分组成,owner是存储的是正在执行的线程(最多只有一个),waitSet是被wait()而正在等待的线程,entryList是竞争锁失败而等待的线程

wait()
当线程被wait()以后会进入waitSet等待队列中

notify()
唤醒waitSet中的一个线程

notifyAll()
唤醒waitSet的所有线程去竞争锁

  • sleep/yield/join

sleep/yield/join 都是Thread的静态方法,他们作用的是本线程
sleep
让线程休眠,但是休眠期间不释放锁.

yield
暂停带线程,将Running状态转变为Runnable状态

join
把本来的异步的线程加入到父线程中,父线程只有等该子线程执行完毕才能继续执行.

       System.out.println(Thread.currentThread().getName() + ",start...");
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + ",start...");
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + ",end...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        t.join();
        System.out.println(Thread.currentThread().getName() + ",end...");

上面的例子中,假如没有t.join(),"main,end..."肯定在"Thread-0,end..."之前,因为Thread-0线程要休眠一分钟;但是如果加了t.join()之后,,"main,end..."在"Thread-0,end..."之后才输出,这是因为join的作用就是让子线程全部执行完才能执行父线程

你可能感兴趣的:(浅谈线程状态)