我用過Samurai,我可以看到沒有死鎖,有幾個線程正在等待,但我似乎無法確切知道哪個鎖正在拖延進程。誰能幫我嗎?解釋jstack trace追蹤失速的鎖
我不是在尋找人來猜測我的問題是什麼,更多關於如何改變代碼的建議,以便更容易地跟蹤問題。我通過我的第一次發送和接收,然後程序停止發送第二條消息。我是新來的多線程,這是我第一次拉jstack
2013-04-02 23:43:12
Full thread dump OpenJDK Zero VM (22.0-b10 mixed mode):
"Attach Listener" daemon prio=10 tid=0x0037c880 nid=0x105b waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
"Thread-3" prio=10 tid=0x0037c488 nid=0x1041 waiting on condition [0xa7ddd000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0xab770958> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
at org.dnsdojo.ryanhost.GA.MuPlusOne.RobotInterface.evaluate(RobotInterface.java:38)
at org.dnsdojo.ryanhost.GA.MuPlusOne.RobotInterface.run(RobotInterface.java:69)
at java.lang.Thread.run(Thread.java:722)
"Thread-1" prio=10 tid=0x0036ff10 nid=0x1036 waiting on condition [0xa7f5d000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0xab770940> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
at org.dnsdojo.ryanhost.GA.MuPlusOne.TwoWaySerialCommTest$SerialWriter.run(TwoWaySerialCommTest.java:229)
at java.lang.Thread.run(Thread.java:722)
"Thread-0" daemon prio=10 tid=0x0036a1e8 nid=0x1035 runnable [0xa80dd000]
java.lang.Thread.State: RUNNABLE
at gnu.io.RXTXPort.eventLoop(Native Method)
at gnu.io.RXTXPort$MonitorThread.run(RXTXPort.java:1644)
"Service Thread" daemon prio=10 tid=0x00253440 nid=0x102b runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x00251988 nid=0x102a runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x0020c880 nid=0x1029 in Object.wait() [0xa8ac1000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0xab718a88> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0xab718a88> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)
"Reference Handler" daemon prio=10 tid=0x00209f18 nid=0x1028 in Object.wait() [0xa8c41000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0xab718b10> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0xab718b10> (a java.lang.ref.Reference$Lock)
"main" prio=10 tid=0x00180fa8 nid=0x1022 in Object.wait() [0xb6848000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0xa90716a8> (a org.dnsdojo.ryanhost.GA.MuPlusOne.CandidateTest)
at java.lang.Object.wait(Object.java:503)
at org.dnsdojo.ryanhost.GA.MuPlusOne.MuPlusOneAlgorithm.runOnBot(MuPlusOneAlgorithm.java:120)
- locked <0xa90716a8> (a org.dnsdojo.ryanhost.GA.MuPlusOne.CandidateTest)
at org.dnsdojo.ryanhost.GA.MuPlusOne.MuPlusOneAlgorithm.initialFitness(MuPlusOneAlgorithm.java:72)
- locked <0xab718bd0> (a org.dnsdojo.ryanhost.GA.MuPlusOne.MuPlusOneAlgorithm)
at org.dnsdojo.ryanhost.GA.MuPlusOne.MuPlusOneAlgorithm.main(MuPlusOneAlgorithm.java:138)
"VM Thread" prio=10 tid=0x00204910 nid=0x1027 runnable
"VM Periodic Task Thread" prio=10 tid=0x00255130 nid=0x102c waiting on condition
JNI global references: 36
添加代碼的要求 串行通信類
package org.dnsdojo.ryanhost.GA.MuPlusOne;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* This version of the TwoWaySerialComm example makes use of the
* SerialPortEventListener to avoid polling.
*
*/
public class TwoWaySerialComm
{
public TwoWaySerialComm()
{
super();
}
void connect (String portName) throws Exception
{
listPorts();
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned())
{
System.out.println("Error: Port is currently in use");
}
else
{
CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
if (commPort instanceof SerialPort)
{
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(57600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
(new Thread(new SerialWriter(out))).start();
serialPort.addEventListener(new SerialReader(in));
serialPort.notifyOnDataAvailable(true);
}
else
{
System.out.println("Error: Only serial ports are handled by this example.");
}
}
}
static void listPorts()
{
java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();
while(portEnum.hasMoreElements())
{
CommPortIdentifier portIdentifier = portEnum.nextElement();
if(portIdentifier == null)
{
System.out.println("No ports");
}
System.out.println("Available - " + portIdentifier.getName());
}
}
/**
* Handles the input coming from the serial port. A new line character
* is treated as the end of a block in this example.
*/
public static class SerialReader implements SerialPortEventListener
{
private InputStream in;
private byte[] buffer = new byte[1024];
public SerialReader (InputStream in)
{
this.in = in;
}
public void serialEvent(SerialPortEvent arg0) {
int data;
try
{
int len = 0;
while ((data = in.read()) > -1)
{
if (data == '\n') {
break;
}
buffer[len++] = (byte) data;
}
System.out.print(new String(buffer,0,len));
}
catch (IOException e)
{
e.printStackTrace();
System.exit(-1);
}
}
}
/** */
public static class SerialWriter implements Runnable
{
OutputStream out;
public SerialWriter (OutputStream out)
{
this.out = out;
}
public void run()
{
try
{
int c = 0;
while ((c = System.in.read()) > -1)
{
this.out.write(c);
}
}
catch (IOException e)
{
e.printStackTrace();
System.exit(-1);
}
}
}
public static void main (String[] args)
{
try
{
(new TwoWaySerialComm()).connect("/dev/ttyS82");
}
catch (Exception e)
{
TwoWaySerialComm.listPorts();
e.printStackTrace();
}
}
}
的RobotInterface類
package org.dnsdojo.ryanhost.GA.MuPlusOne;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class RobotInterface implements Runnable
{
// create a serial connection
// transmit a string and check for response
// wait for evaluation
// take evaluation
private CandidateTest candidate;
private TwoWaySerialCommTest serialConnection;
//private Random rng = new Random();
protected static Logger logger = Logger.getLogger("Thread" + Thread.currentThread().getName());
public RobotInterface(CandidateTest test, TwoWaySerialCommTest serialConnection)
{
this.candidate = test;
this.serialConnection = serialConnection;
PropertyConfigurator.configure("log4j.properties");
}
public void evaluate (Genome genome)
{
//send to robot and return fitness
//genome.setFitness(rng.nextDouble());
logger.debug("fitness is " + genome.getFitness());
try
{
String s = candidate.getCandidate().toString();
System.out.println(s);
TwoWaySerialCommTest.lock.lock();
System.out.println(s);
serialConnection.put(s);
TwoWaySerialCommTest.inputAvailable.await();
try
{
candidate.getCandidate().setFitness(Float.parseFloat(serialConnection.take()));
}
catch(Exception e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
TwoWaySerialCommTest.listPorts();
e.printStackTrace();
}
finally
{
TwoWaySerialCommTest.lock.unlock();
}
}
public void run()
{
logger.debug("entering run of Robot Interface");
logger.debug("Send Genome via serial and wait for a response");
Genome testSubject = candidate.getCandidate();
evaluate(testSubject);
candidate.finished();
}
}
總結執行 - 我有一個for循環創建RobotInterface線程,每個線程都包含一個位串。該基因組引用保存在候選測試中,該候選測試僅僅是RobotInterface的共享類和調用線程在完成時發出信號。
使用TwoWaySerialCommTest通過RobotInterface將位串發送給機器人。機器人對其進行評估並返回一個適應函數,該函數由SerialReader解析爲一個浮點數。下一個字符串然後被髮送給機器人。
鎖定發生在第一個字符串返回到機器人併發送第二個字符串之後。我可以看到第一個字符串將其傳遞給機器人,但第二個字符串沒有。輸出如下 -
initialFitness method
1101010101111111001100000101011100110000100001111111001000001001101101000011100101011000000100000000110110001110
5436 [main] DEBUG org.dnsdojo.ryanhost.GA.MuPlusOne.GeneticAlgorithm - Testing candidate
1101010101111111001100000101011100110000100001111111001000001001101101000011100101011000000100000000110110001110
1101010101111111001100000101011100110000100001111111001000001001101101000011100101011000000100000000110110001110
5853 [Thread-2] DEBUG Threadmain - entering run of Robot Interface
5869 [Thread-2] DEBUG Threadmain - Send Genome via serial and wait for a response
5881 [Thread-2] DEBUG Threadmain - fitness is 0.0
1101010101111111001100000101011100110000100001111111001000001001101101000011100101011000000100000000110110001110
1101010101111111001100000101011100110000100001111111001000001001101101000011100101011000000100000000110110001110
10
Output buffer after put
1101010101111111001100000101011100110000100001111111001000001001101101000011100101011000000100000000110110001110
Buffer isn't empty
initialFitness method
1110110101110000001100101100110001001010010101011110001101010010100100111011111000011101110000001110100111001111
16593 [main] DEBUG org.dnsdojo.ryanhost.GA.MuPlusOne.GeneticAlgorithm - Testing candidate
1110110101110000001100101100110001001010010101011110001101010010100100111011111000011101110000001110100111001111
1110110101110000001100101100110001001010010101011110001101010010100100111011111000011101110000001110100111001111
16944 [Thread-3] DEBUG Threadmain - entering run of Robot Interface
16953 [Thread-3] DEBUG Threadmain - Send Genome via serial and wait for a response
16964 [Thread-3] DEBUG Threadmain - fitness is 0.0
1110110101110000001100101100110001001010010101011110001101010010100100111011111000011101110000001110100111001111
1110110101110000001100101100110001001010010101011110001101010010100100111011111000011101110000001110100111001111
10
Output buffer after put
1110110101110000001100101100110001001010010101011110001101010010100100111011111000011101110000001110100111001111
Buffer isn't empty
謝謝,我已經添加了代碼的問題,因爲你可以看到它是相當一線的球:(我正在通過它自己在此刻根據你的一般答案,這是相當有幫助 – SMC
我是當我從串口讀取時,認爲我的問題在RobotInterface類中,也許鎖在雙嘗試/捕獲中沒有被正確釋放? – SMC
因此,在我將這個頭撞了很長時間之後,事實證明問題與串行連接沒有確認和響應某些字符串有關,但是您的建議確實幫助我排除了線程問題,所以感謝上百萬 – SMC