线程被创建完,但是还没有调用start()方法启动线程
1 | public class StateNew { |
输出结果:
1 | myThread: NEW |
表明当前线程已经在执行(RUNNING)或者在等待系统调度执行(READY)。
1 | public class StateRunnable implements Runnable { |
输出结果:
1 | myThread: RUNNABLE |
线程调用 Object.wait()
、Thread.join()
、LockSupport.park()
等方法时会进入等待状态
1 | public class StateWaiting implements Runnable { |
执行 jps
命令查看线程ID
1 | 4560 Jps |
然后执行 jstack
查看线程信息
1 | jstack 4546 |
输出结果如下:
1 | "myThread" #12 prio=5 os_prio=31 tid=0x00007fbdfa13c000 nid=0x4403 in Object.wait() [0x000070000a80e000] |
从中可以看出:
object.wait()
而处于 WAITING
状态,在等待其他线程唤起thread.join()
而处于 WAITING
状态,在等待 myThread 执行结束线程调用 Thread.sleep(long)
、Object.wait(long)
、Thread.join(long)
、 LockSupport.parkNanos
、LockSupport.parkUntil
等方法时会进入超时等待状态
把上面的代码改为超时等待
1 | public class StateTimeWaiting implements Runnable { |
查看结果
1 | "myThread" #12 prio=5 os_prio=31 tid=0x00007facf50d6800 nid=0x4103 in Object.wait() [0x000070000a3c3000] |
状态变为 TIMED_WAITING
线程已经执行完,线程对象可能还存活,但是不能再次执行
上半年遇到了一次类加载死锁的问题,花了挺长时间才定位到具体原因,因此做个记录,以便下次遇到类似问题时可以快速定位。
在多线程环境下,如果要访问共享变量,通常要使用同步机制来保证访问的正确性。如果变量不需要共享,可以将其移到单个线程内,这样就不需要同步操作。ThreadLocal 把线程和要使用的对象关联起来,线程自己保存一份独立的副本,从而实现了数据访问的安全性。
本文讲的是:在 linux 环境下,定位 cpu 使用率最高的 java 线程,找出对应代码的方法。基本思路是:使用 top
命令找出 cpu 占用率最高的 java 线程,然后结合 jstack
定位问题代码。