线程状态总结转自:http://kyfxbl.iteye.com/blog/1370377public class ThreadA {public static void main(
线程状态总结
转自:http://kyfxbl.iteye.com/blog/1370377
public class ThreadA { public static void main(String[] args) { ThreadB b = new ThreadB();// ThreadB status: new b.start();// ThreadB status: runnable synchronized (b) { try { System.out.println("等待对象b完成计算。。。"); Thread.sleep(60000); b.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("b对象计算的总和是:" + b.total); } } } public class ThreadB extends Thread { int total; public void run() { synchronized (this) { for (int i = 0; i < 101; i++) { total += i; } notifyAll(); } } } ?jstack输出的结果是:
"main" prio=6 tid=0x00846800 nid=0x1638 waiting on condition [0x0092f000]
?? java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at net.kyfxbl.lock.ThreadA.main(ThreadA.java:20)
- locked <0x22a18a90> (a net.kyfxbl.lock.ThreadB)
"Thread-0" prio=6 tid=0x02bbb800 nid=0x1410 waiting for monitor entry [0x02f0f000]
?? java.lang.Thread.State: BLOCKED (on object monitor)
at net.kyfxbl.lock.ThreadB.run(ThreadB.java:11)
- waiting to lock <0x22a18a90> (a net.kyfxbl.lock.ThreadB)
可以看到,主线程和新线程在同一个对象上锁定,主线程的方法里执行了Thread.sleep(60000),因此进入了TIMED_WAITING状态,而新线程则进入BLOCKED状态
public class ThreadA {public static void main(String[] args) {ThreadB b = new ThreadB();// ThreadB status: newb.start();// ThreadB status: runnablesynchronized (b) {try {System.out.println("等待对象b完成计算。。。");b.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("b对象计算的总和是:" + b.total);}}}public class ThreadB extends Thread {int total;public void run() {synchronized (this) {try {Thread.sleep(60000);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 101; i++) {total += i;}notifyAll();}}}
jstack输出的结果是:
"main" prio=6 tid=0x00846800 nid=0x1684 in Object.wait() [0x0092f000]
?? java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x22a18b08> (a net.kyfxbl.lock.ThreadB)
at java.lang.Object.wait(Object.java:485)
at net.kyfxbl.lock.ThreadA.main(ThreadA.java:22)
- locked <0x22a18b08> (a net.kyfxbl.lock.ThreadB)
"Thread-0" prio=6 tid=0x02bcc800 nid=0x19c waiting on condition [0x02f0f000]
?? java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at net.kyfxbl.lock.ThreadB.run(ThreadB.java:12)
- locked <0x22a18b08> (a net.kyfxbl.lock.ThreadB)
2个线程还是在同一个对象上同步,但这次主线程立刻执行了b.wait()方法,因此释放了对象b上的锁,自己进入了WAITING状态。接下来新线程得到了对象b上的锁,所以没有进入阻塞状态,紧接着执行Thread.sleep(60000)方法,进入了TIMED_WAITING状态
public class ThreadA {public static void main(String[] args) {ThreadB b = new ThreadB();// ThreadB status: newb.start();// ThreadB status: runnablesynchronized (b) {try {System.out.println("等待对象b完成计算。。。");b.wait();// ThreadB status: running} catch (InterruptedException e) {e.printStackTrace();}System.out.println("b对象计算的总和是:" + b.total);}}}public class ThreadB extends Thread {int total;public void run() {synchronized (this) {for (int i = 0; i < 101; i++) {total += i;}notifyAll();try {System.out.println("我要睡了");Thread.sleep(60000);} catch (InterruptedException e) {e.printStackTrace();}}}}
jstack输出的结果是:
"main" prio=6 tid=0x00846800 nid=0x3ec in Object.wait() [0x0092f000]
?? java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x22a18ba0> (a net.kyfxbl.lock.ThreadB)
at java.lang.Object.wait(Object.java:485)
at net.kyfxbl.lock.ThreadA.main(ThreadA.java:20)
- locked <0x22a18ba0> (a net.kyfxbl.lock.ThreadB)
"Thread-0" prio=6 tid=0x02bbb800 nid=0x14b4 waiting on condition [0x02f0f000]
?? java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at net.kyfxbl.lock.ThreadB.run(ThreadB.java:19)
- locked <0x22a18ba0> (a net.kyfxbl.lock.ThreadB)
当主线程执行b.wait()之后,就进入了WAITING状态,但是新线程执行notifyAll()之后,有一个瞬间主线程回到了RUNNABLE状态,但是好景不长,由于这个时候新线程还没有释放锁,所以主线程立刻进入了BLOCKED状态
12、当在对象上调用wait()方法时,执行该代码的线程立即放弃它在对象上的锁。然而调用notify()时,并不意味着这时线程会放弃其锁。如果线程仍然在完成同步代码,则线程在移出之前不会放弃锁。因此,只要调用notify()并不意味着这时该锁被释放
13、与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。
14、在一个线程中开启另外一个新线程,则新开线程称为该线程的子线程,子线程初始优先级与父线程相同。
15、JRE判断程序是否执行结束的标准是所有的前台执线程行完毕了,而不管后台线程的状态,因此,在使用后台线程时候一定要注意这个问题。
16、下面说说我们这次JBOSS挂死问题的处理方法
现象:系统运行一段时间之后,发现有几个子系统无法访问了,但是另外几个可以。CPU占用达到100%
观察了一下,发现无法访问的应用都部署在同一个JBOSS里,于是把该JBOSS的堆栈用jstack命令输出
发现里面有大量的线程处于BLOCKED状态,均是在执行到c3p0的一个方法里的某一行时,BLOCKED住了
于是下载c3p0的源码,跟进去看了一下,这是一个同步方法,内部会去获取数据库连接,如果获取到连接,就进行下一步操作,如果获取不到,就执行sleep(long timeout)方法。
反推一下,我猜测可能是这样的:
由于某段代码没有释放数据库连接-->连接池中的连接耗尽-->部分线程无限TIMED_WAITING-->其余线程都BLOCKED-->开启新线程-->频繁引发GC-->占用大量CPU-->应用挂起
后来对所有涉及到数据库连接的代码进行排查,发现确实有几个地方做完数据库操作以后,没有释放连接。把这部分代码改掉,重新启动JBOSS,没有再出现JBOSS挂起的现象