多次start一个线程会怎么样
第二遍会报错Exception in thread "main" java.lang.IllegalThreadStateException
原因 threadStatus 初始值是0 跑过一次后是个非0的值 在第二遍就会报错
怎么查看服务器的死锁
java 死锁产生的四个必要条件:
- 1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
- 2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
- 3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
- 4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
方式一
jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。
首先,我们通过jps确定当前执行任务的进程号:
//查看服务进程 还可以用 ps -aux |grep 名字 来查看的
[root@10 app]# jps
2848 jar
2942 Jps
// 这个命令来检测死锁
[root@10 app]# jstack -F 2848
Attaching to process ID 2848, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.333-b02
Deadlock Detection:
//找到死锁了
Found one Java-level deadlock:
=============================
"Thread-3":
waiting to lock Monitor@0x00007f0444005ea8 (Object@0x00000000f632b640, a java/lang/String),
which is held by "Thread-4"
"Thread-4":
waiting to lock Monitor@0x00007f04440062c8 (Object@0x00000000f632b610, a java/lang/String),
which is held by "Thread-2"
"Thread-2":
waiting to lock Monitor@0x00007f04440038d8 (Object@0x00000000f632b628, a java/lang/String),
which is held by "Thread-3"
Found a total of 1 deadlock.
//最后会打印死锁
Thread 2852: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- java.lang.ref.ReferenceQueue.remove(long) @bci=59, line=150 (Compiled frame)
- java.lang.ref.ReferenceQueue.remove() @bci=2, line=171 (Compiled frame)
- java.lang.ref.Finalizer$FinalizerThread.run() @bci=36, line=216 (Interpreted frame)
Thread 2851: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- java.lang.Object.wait() @bci=2, line=502 (Compiled frame)
- java.lang.ref.Reference.tryHandlePending(boolean) @bci=54, line=191 (Compiled frame)
- java.lang.ref.Reference$ReferenceHandler.run() @bci=1, line=153 (Interpreted frame)
方式二
使用arthas 执行 thread -b 可以检查死锁
执行后如果有死锁直接就输出详细信息了。
死锁代码示例
private String lock1="lock1";
private String lock2="lock2";
private String lock3="lock3";
public void test(){
new Thread(()->{
synchronized (lock1){
System.out.println("占用了1锁 准备锁2");
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (lock2){
System.out.println("占用了1锁 占用锁2");
}
}
}).start();
new Thread(()->{
synchronized (lock2){
System.out.println("占用了2锁 准备锁3");
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (lock3){
System.out.println("占用了2锁 占用锁3");
}
}
}).start();
new Thread(()->{
synchronized (lock3){
System.out.println("占用了3锁 准备锁1");
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (lock1){
System.out.println("占用了3锁 占用锁1");
}
}
}).start();
}