什么是要做?
- 从这里下载 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
方法。
怎么了?
s 被阻塞(大概是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
因此,当我的测试应用程序被执行时,ONE
Thread
进入 PDU 的静态方法(在初始化时DataSM
)。Thread
而已经开始初始化的 TWOOutbind
等待 ONE 完成初始化PDU
。但是在运行静态方法的 ONE 中的某个时刻
PDU
,它尝试初始化Outbind
,并且看到 TWO 已经开始了相同的事情,它等待 TWO 完成。所以一和二在等待对方完成
我怎么能确信这个问题与静态块加载有关?
在测试代码的 main 方法中添加以下一行作为第一条语句,使其工作并且Thread
s 不再阻塞: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。他们不保留任何外部资源,如文件、数据库等。