线程所争夺的资源可以是:锁、网络连接、通知事件、磁盘、带宽,以及一切可以称为“资源”的东西。程序在执行的时候,难免会遇到死锁的情况。下面介绍如何解决Java中的死锁线程。先来一个死锁的例子:importjava.util.concurrent.TimeUnit;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassReentrantLockDeadLock{staticLocklock1=newReentrantLock();静态锁lock2=newReentrantLock();publicstaticvoidmain(String[]args)throwsInterruptedException{Threadthread1=newThread(newDeadLockDemo(lock1,lock2),"Thread1");线程thread2=newThread(newDeadLockDemo(lock2,lock1),"Thread2");thread1.start();thread2.start();}staticclassDeadLockDemoimplementsRunnable{LocklockA;锁锁B;publicDeadLockDemo(LocklockA,LocklockB){this.lockA=lockA;这个.lockB=lockB;}@Overridepublicvoidrun(){try{lockA.lock();System.out.println(Thread.currentThread().getName()+"\t自己持有:"+lockA+"\t尝试获得:"+lockB);TimeUnit.SECONDS.sleep(2);lockB.lock();System.out.println(Thread.currentThread().getName()+"\t自己持有:"+lockB+"\t尝试获取:"+lockA);}catch(InterruptedExceptione){e.printStackTrace();}最后{lockA.unlock();锁B.解锁();System.out.println(Thread.currentThread().getName()+"正常结束!");}}}}执行这个类,可以明显看出程序不会自动结束,说明还有线程在占用资源或者等待资源首先使用jps命令列出当前Java进程:使用一些工具抓取死锁线程。1、jstack找一个疑似死锁的例子,找到PID。上图中可以看到20148线程就是我执行上面死锁的例子:>jstack-l2014820148com.yudianxx.basic.Thread.ReentrantLock.ReentrantLockDeadLockjps-l;-l参数可以显示完整的启动类。执行jstack-l20148往下看,会显示一个deadlock关键字:见下图,提示:atcom.yudianxx.basic.thread.ReentrantLock.ReentrantLockDeadLock$DeadLockDemo.run(ReentrantLockDeadLock.java:39)是lockB这一行。ReentrantLockDeadLock类下的lock()。您可以找到死锁的类和行号。2、jconsolejconsole位于JDK的bin目录下,双击运行即可。如下,选择需要建立连接的进程。切换到Thread,然后点击底部的DetectDeadlock,查看死锁情况:另外jconsole还可以查看其他信息,比如堆内存,CPU,线程数等。3.jvisualvmjvisualvm也在bin目录下JDK。选择一个本地进程,切换到顶部的Thread,然后单击ThreadDump。点击后可以看到线程的状态日志,可以看到死锁信息:4.jmc也位于JDK的bin目录下。打开需要监控的进程:切换到下面的线程图,可以看到死锁标志。以上就是定位java线程死锁的工具。推荐使用jstack命令。毕竟,最后三个工具在Linux中是没有的。jstack可以通过查找类入口,然后找出当前线程在等待哪个线程,进而定位死锁行数来定位死锁的原因。
