java 线程 block_JAVA线程的BLOCK状态实例分析

今天主要介绍一下线程block的状态,从实例来分析线程的block状态。

背景

先介绍一下线程的所有状态信息

NEW: 线程创建之后,但是还没有启动(not yet started)。这时候它的状态就是NEW RUNNABLE: 正在Java虚拟机下跑任务的线程的状态。在RUNNABLE状态下的线程可能会处于等待状态, 因为它正在等待一些系统资源的释放,比如IO BLOCKED: 阻塞状态,等待锁的释放,比如线程A进入了一个synchronized方法,线程B也想进入这个方法,但是这个方法的锁已经被线程A获取了,这个时候线程B就处于BLOCKED状态 WAITING: 等待状态,处于等待状态的线程是由于执行了3个方法中的任意方法。 1. Object的wait方法,并且没有使用timeout参数; 2. Thread的join方法,没有使用timeout参数 3. LockSupport的park方法。 处于waiting状态的线程会等待另外一个线程处理特殊的行为。 再举个例子,如果一个线程调用了一个对象的wait方法,那么这个线程就会处于waiting状态直到另外一个线程调用这个对象的notify或者notifyAll方法后才会解除这个状态 TIMED_WAITING: 有等待时间的等待状态,比如调用了以下几个方法中的任意方法,并且指定了等待时间,线程就会处于这个状态。 1. Thread.sleep方法 2. Object的wait方法,带有时间 3. Thread.join方法,带有时间 4. LockSupport的parkNanos方法,带有时间 5. LockSupport的parkUntil方法,带有时间 TERMINATED: 线程中止的状态,这个线程已经完整地执行了它的任务

经典线程状态流转图

示例

下面是示例代码。package com.alibaba.lepao; import lombok.Data; /** * 死锁DEMO */ public class Test { //定义两把锁 static UserLock lock1 = new UserLock(); static UserLock lock2 = new UserLock(); public static class Task1 implements Runnable { @Override public void run() { synchronized (lock1) { System.out.println(Thread.currentThread().getName() + " 获得了第一把锁!!"); try { //等待另外一个线程占用第二把锁 Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } //此处死锁 synchronized (lock2) { System.out.println(Thread.currentThread().getName() + " 获得了第二把锁!!"); } } } } public static class Task2 implements Runnable { @Override public void run() { synchronized (lock2) { System.out.println(Thread.currentThread().getName() + " 获得了第二把锁!!"); //此处死锁 synchronized (lock1) { System.out.println(Thread.currentThread().getName() + " 获得了第一把锁!!"); } } } } public static void main(String[] arg) throws InterruptedException { Thread thread1 = new Thread(new Task1(), "task-1"); Thread thread2 = new Thread(new Task2(), "task-2"); //启动两个线程 thread1.start(); thread2.start(); //主线程等待子线程,防止主线程退出导致子线程退出 thread1.join(); thread2.join(); System.out.println(Thread.currentThread().getName() + " 执行结束!"); } @Data public static class UserLock{ private String name; } }

代码执行后输出入下图:

程序进入死锁BLOCK状态,及线程1等待第二把锁,线程2等待第一把锁。

分析

我们继续DUMP线程,可以得到如下的信息

可以看到,此时的线程是BLOCK状态,即两个线程都在等待锁。

DUMP线程信息获取java进程

jps -l获取线程信息

jstack -l 47142

总结

可以看到,线程在BLOCK状态就是线程获取锁的状态,大量处在BLOCK状态的线程,可能就引发了死锁,系统发生死锁现象不仅浪费大量的系统资源,甚至导致整个系统崩溃,带来灾难性后果。所以,对于死锁问题在理论上和技术上都必须予以高度重视。

另外大量线程BLOCK由于会占用线程资源,无法对外提供服务,可能引起线程池满,造成整个系统无法提供服务。

你可能感兴趣的:(java,线程,block)