java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明:  
  • NEW:至今尚未启动的线程的状态。
  • RUNNABLE:可运行线程的线程状态。处于可运行状态的某一线程正在 Java 虚拟机中运行,但它可能正在等待操作系统中的其他资源,比如处理器。
  • BLOCKED :受阻塞并且正在等待监视器锁的某一线程的线程状态。处于受阻塞状态的某一线程正在等待监视器锁,以便进入一个同步的块/方法,或者在调用 Object.wait()之后再次进入同步的块/方法。
  • WAITING: 处于等待状态的线程正等待另一个线程,以执行特定操作。 例如,已经在某一对象上调用了 Object.wait() 的线程正等待另一个线程,以便在该对象上调用 Object.notify()Object.notifyAll()。已经调用了 Thread.join() 的线程正在等待指定线程终止。[Thread.sleep()、不带超时设置的Object.wait()、不代超时值的Thread.join()]  
  • TIMED_WAITING:具有指定等待时间的某一等待线程的线程状态。某一线程因为调用以下带有指定正等待时间的方法之一而处于定时等待状态:[Thread.sleep()、带超时设置的Object.wait()、代超时值的Thread.join()]  
  • TERMINATED:已终止线程的线程状态。线程已经结束执行。

下面谈谈如何让线程进入以上几种状态:

1. NEW, 这个最简单了
static void NEW() {
Thread t = new Thread ();
System. out.println(t.getState());
}

2. RUNNABLE, 也简单, 让一个thread start, 同时代码里面不要sleep或者wait等

 private static void RUNNABLE() {
Thread t = new Thread(){
public void run(){
for(int i=0; i<Integer.MAX_VALUE; i++){
System. out.println(i);
}
}
};
t.start();
}

3. BLOCKED, 这个就必须至少两个线程以上, 然后互相等待synchronized 块

 private static void BLOCKED() {
final Object lock = new Object();
Runnable run = new Runnable() {
@Override
public void run() {
for(int i=0; i<Integer.MAX_VALUE; i++){
synchronized (lock) {
System. out.println(i);
}
}
}
};
Thread t1 = new Thread(run);
t1.setName( “t1″);
Thread t2 = new Thread(run);
t2.setName( “t2″);
t1.start();
t2.start();
}
  这时候, 一个在RUNNABLE, 另一个就会在BLOCKED (等待另一个线程的 System.out.println.. 这是个IO操作, 属于系统资源, 不会造成WAITING等)
  4. WAITING, 这个需要用到生产者消费者模型, 当生产者生产过慢的时候, 消费者就会等待生产者的下一次notify

 private static void WAITING() {
final Object lock = new Object();
Thread t1 = new Thread(){
@Override
public void run() {
int i = 0;
while(true ){
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
}
System. out.println(i++);
}
}
}
};
Thread t2 = new Thread(){
@Override
public void run() {
while(true ){
synchronized (lock) {
for(int i = 0; i< 10000000; i++){
System. out.println(i);
}
lock.notifyAll();
} }
}
};
t1.setName( “^^t1^^”);
t2.setName( “^^t2^^”);
t1.start();
t2.start();
}
 5. TIMED_WAITING, 这个仅需要在4的基础上, 在wait方法加上一个时间参数进行限制就OK了.把4中的synchronized 块改成如下就可以了.
synchronized (lock) {
try {
lock.wait(60 * 1000L);
} catch (InterruptedException e) {
}
System. out .println(i++);
}
  另外看stack的输出,  他叫 TIMED_WAITING(on  object monitor) , 说明括号后面还有其他的情况, 比如sleep, 我们直接把t2的for循环改成sleep试试:
synchronized (lock) {
try {
sleep(30*1000L);
} catch (InterruptedException e) {
}
lock.notifyAll();
}
  看到了吧, t2的state是 TIMED_WAITING( sleeping),  而t1依然是on object monitor , 因为t1还是wait在等待t2 notify, 而t2是自己sleep另外, join操作也是进入 on object monitor

  6. TERMINATED, 这个状态只要线程结束了run方法, 就会进入了…

private static void TERMINATED() {
Thread t1 = new Thread();
t1.start();
System. out.println(t1.getState());
try {
Thread. sleep(1000L);
} catch (InterruptedException e) {
}
System. out.println(t1.getState());
}

  输出:

RUNNABLE
TERMINATED

  由于线程的start方法是异步启动的, 所以在其执行后立即获取状态有可能才刚进入RUN方法且还未执行完毕.

  好吧, 一句话, 在找到系统中的潜在性能瓶颈有作用.当java系统运行慢的时候, 我们想到的应该先找到性能的瓶颈, 而jstack等工具, 通过jvm当前的stack可以看到当前整个vm所有线程的状态, 当我们看到一个线程状态经常处于WAITING 或者 BLOCKED的时候, 要小心了, 他可能在等待资源经常没有得到释放(当然, 线程池的调度用的也是各种队列各种锁, 要区分一下, 比如下图)

  这是个经典的并发包里面的线程池, 其调度队列用的是LinkedBlockingQueue, 执行take的时候会block住, 等待下一个任务进入队列中, 然后进入执行, 这种理论上不是系统的性能瓶颈, 找瓶颈一般先找自己的代码stack,再去排查那些开源的组件/JDK的问题

排查问题的几个思路:

1.如何跟踪一个线程?

  看到上面的stack输出没有, 第一行是内容是 threadName priority tid nid desc更过跟踪tid, nid 都可以唯一找到该线程.

  1. 发现有线程进入BLOCK, 而且持续好久, 这说明性能瓶颈存在于synchronized块中, 因为他一直block住, 进不去, 说明另一个线程一直没有处理好, 也就这个synchronized块中处理速度比较慢, 然后再深入查看. 当然也有可能同时block的线程太多, 排队太久造成.
  2. 发现有线程进入WAITING, 而且持续好久, 说明性能瓶颈存在于触发notify的那段逻辑. 当然还有就是同时WAITING的线程过多, 老是等不到释放.
  3. 线程进入TIME_WAITING 状态且持续好久的, 跟2的排查方式一样.

  上面的黑底白字截图都是通过jstack打印出来的, 可以直接定位到你想知道的线程的执行栈, 这对java性能瓶颈的分析是有极大作用的.

JAVA中线程的状态的更多相关文章

  1. java中线程的状态详解

    一.线程的五种状态   线程的生命周期可以大致分为5种,但这种说法是比较旧的一种说法,有点过时了,或者更确切的来说,这是操作系统的说法,而不是java的说法.但对下面所说的六种状态的理解有所帮助,所以 ...

  2. 并发基础(四) java中线程的状态

    一.程的五种状态   线程的生命周期可以大致分为5种,但这种说法是比较旧的一种说法,有点过时了,或者更确切的来说,这是操作系统的说法,而不是java的说法.但对下面所说的六种状态的理解有所帮助,所以也 ...

  3. Java中线程的状态及其转化

    线程状态转化图: 说明: 线程总共包括以下5种状态. 1.新状态New:该状态也叫新建状态,当线程对象被创建后,线程就进入了新建状态.例如:Thread thread = new Thread();. ...

  4. JAVA中线程同步方法

    JAVA中线程同步方法 1  wait方法:         该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所 ...

  5. 多线程(三) java中线程的简单使用

    java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依 ...

  6. 沉淀再出发:java中线程池解析

    沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...

  7. Java多线程并发03——在Java中线程是如何调度的

    在前两篇文章中,我们已经了解了关于线程的创建与常用方法等相关知识.接下来就来了解下,当你运行线程时,线程是如何调度的.关注我的公众号「Java面典」了解更多 Java 相关知识点. 多任务系统往往需要 ...

  8. java中线程分两种,守护线程和用户线程。

    java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...

  9. java中线程机制

    java中线程机制,一开始我们都用的单线程.现在接触到多线程了. 多线性首先要解决的问题是:创建线程,怎么创建线程的问题: 1.线程的创建: 四种常用的实现方法 1.继承Thread. Thread是 ...

随机推荐

  1. node.js平台下,利用cookie实现记住密码登陆(Express+Ejs+Mysql)

    本博文需有node.js+express+mysql入门基础,若基础薄弱,可参考博主的其他几篇node.就是博文: 1.下载Mysql数据库,安装并配置 创建用户表供登录使用: 2.node.js平台 ...

  2. AE + GDAL实现影像按标准图幅分割(上)

    最近有个项目,其中有个功能是要将遥感影像按标准图幅分割,一开始用AE的接口,慢的让人抓狂,就改用GDAL,速度提升很大.我主要通过http://blog.csdn.net/liminlu0314/学习 ...

  3. Linux网络那点事

    跨平台系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#linux 之前的之前说过网络自连接的配置(CentOS服务器网络配置:http://ww ...

  4. Java ---理解MVC架构

    之间的文章,我们主要是介绍了jsp的相关语法操作,我们可以通过请求某个jsp页面,然后由相对应的servlet实例给我们返回html页面.但是在实际的项目中,我们很少会直接的请求某个页面,一般都是请求 ...

  5. 《ECMAScript标准入门》第二版读书笔记

    title: <ECMAScript标准入门>第二版 date: 2017-04-10 tags: JavaScript categories: Reading-note 2015年6月, ...

  6. Linux服务器性能查看分析调优

    一 linux服务器性能查看 1.1 cpu性能查看 1.查看物理cpu个数: cat /proc/cpuinfo |grep "physical id"|sort|uniq|wc ...

  7. OpenDigg安卓开源项目月报201704

    由OpenDigg 出品的安卓开源项目月报第一期来啦.我们的安卓开源月报集合了OpenDigg一个月来新收录的优质安卓开源项目,方便安卓开发人员便捷的找到自己需要的项目工具. DiscreteScro ...

  8. SQL模糊查询条件的四种匹配模式

    执行数据库查询时,有完整查询和模糊查询之分. 一般模糊语句格式如下: SELECT 字段 FROM 表 WHERE 某字段 LIKE 条件 其中关于条件,SQL提供了四种匹配模式: 1.% :表示任意 ...

  9. weex里Vuex state使用storage持久化

    在weex里使用Vuex作为state管理工具,问题来了,如何使得state可以持久化呢?weex官方提供store模块,因此我们可以尝试使用该模块来持久化state. 先看下该模块介绍: stora ...

  10. asp.net core源码飘香:Logging组件

    简介: 作为基础组件,日志组件被其他组件和中间件所使用,它提供了一个统一的编程模型,即不需要知道日志最终记录到哪里去,只需要调用它即可. 使用方法很简单,通过依赖注入ILogFactory(Creat ...