什么是要做?
从此处下载logica smpp jar(215 KB):http://opensmpp.logica.com/CommonPart/Download/library_1_3/smpp_full.tar.gz
编写一个小的测试代码:
package com.logica.smpp;
import com.logica.smpp.pdu.DataSM;
import com.logica.smpp.pdu.Outbind;
public class PDUTest {
public static void main(String... args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(new DataSM().debugString());
}
});
thread1.setName("ONE");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(new Outbind().debugString());
}
});
thread2.setName("TWO");
thread1.start();
thread2.start();
}
}
运行此
main
方法。怎么了?
Thread
被阻止(可能正在等待对方)我的分析:
DataSM
和Outbind
类都有一个共同的祖先PDU
,它有一个static
块,其代码如下:static {
pduList = new Vector(30,4);
pduList.add(new BindTransmitter());
pduList.add(new BindTransmitterResp());
pduList.add(new BindReceiver());
pduList.add(new BindReceiverResp());
pduList.add(new BindTransciever());
pduList.add(new BindTranscieverResp());
pduList.add(new Unbind());
pduList.add(new UnbindResp());
pduList.add(new Outbind());
pduList.add(new SubmitSM());
pduList.add(new SubmitSMResp());
pduList.add(new SubmitMultiSM());
pduList.add(new SubmitMultiSMResp());
pduList.add(new DeliverSM());
pduList.add(new DeliverSMResp());
pduList.add(new DataSM());
pduList.add(new DataSMResp());
pduList.add(new QuerySM());
pduList.add(new QuerySMResp());
pduList.add(new CancelSM());
pduList.add(new CancelSMResp());
pduList.add(new ReplaceSM());
pduList.add(new ReplaceSMResp());
pduList.add(new EnquireLink());
pduList.add(new EnquireLinkResp());
pduList.add(new AlertNotification());
pduList.add(new GenericNack());
}
它创建
pduList
,以便可以通过其在BindTransmitter
中提供的工厂方法创建其子对象,例如DataSM
,Outbind
,createPDU
等。因此,当我的测试应用程序执行时,一个
Thread
进入PDU的静态方法(初始化DataSM
时)。并且已开始初始化Thread
的两个Outbind
等待ONE完成初始化PDU
。但是在运行
PDU
的静态方法的ONE中的某个点,它尝试初始化Outbind
,并且看到两个已经开始执行相同的操作,它等待两个完成。所以一个和两个正在等待对方完成
我如何确定此问题与静态块加载有关?
在测试代码main方法的第一条语句中仅添加以下这一行,使其可以工作,并且
Thread
不再阻塞:Class.forName("com.logica.smpp.pdu.PDU");
我的问题是:
我的分析正确吗?
这是与静态块有关的已知的
Thread
同步问题吗?是否需要实践任何经验法则以免绊倒这种情况?
更新资料
在此处为PDU添加工厂方法:
public static final PDU createPDU(int commandId)
{
int size = pduList.size();
PDU pdu = null;
PDU newInstance = null;
for (int i = 0; i < size; i++) {
pdu = (PDU)pduList.get(i);
if (pdu != null) {
if (pdu.getCommandId() == commandId) {
try {
newInstance = (PDU)(pdu.getClass().newInstance());
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
}
return newInstance;
}
}
}
return null;
}
DataSM
,Outbind
和其他PDU
子类的构造函数做什么?除了初始化一些实例变量外,什么都没有。这些是POJO。它们不保留任何外部资源,例如文件,数据库等。
最佳答案
您的线程可能正在阻塞,但并非出于您的考虑原因。静态初始化程序在加载类时执行,而不是在创建实例时执行。因此,您不必让两个对象“进入”静态初始值设定项,并在某个时候陷入某个共享变量的死锁状态。
在不知道所用库的确切细节的情况下,很难诊断出真正的问题是什么,但是我建议您转储线程并使用一个不错的工具对其进行分析。
How to Take a Thread Dump
Thread Dump Analysis Tool
关于java - Java-静态块和线程同步问题-现有案例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15048971/