要做什么?
- 从此处下载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
方法。
会发生什么?
线程
被阻塞(大概是在互相等待)
我的分析:
DataSM
和Outbind
类都有一个共同的祖先PDU
,它有一个static
block 使用以下代码: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
)。两个线程
已开始初始化Outbind
,等待其中一个完成初始化PDU
。但是在运行
PDU
静态方法的 ONE 中的某个时刻,它尝试初始化Outbind
,并且看到 TWO 已经启动了相同的操作,它等待 TWO 完成。所以一和二正在等待对方完成
我如何才能确信此问题与静态 block 加载有关?
只需添加以下一行作为测试代码的 main 方法中的第一条语句,即可使其正常工作,并且Thread
不再阻塞:Class.forName("com.logica.smpp.pdu.PDU");
我的问题是:
- 我的分析正确吗?
- 这是与静态 block 相关的已知
线程
同步问题吗? - 需要练习什么经验法则才能避免遇到这种情况?
更新
在此处添加 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。他们不保留任何外部资源,如文件、数据库等。
最佳答案
您的线程可能会阻塞,但原因并非您想象的那样。静态初始值设定项在类加载时执行,而不是在创建实例时执行。因此,您不会让两个对象“进入”静态初始化程序,并在某个时刻在某些共享变量上陷入僵局。
如果不知道您正在使用的库的确切细节,就很难诊断真正的问题是什么,但我建议转储您的线程并使用合适的工具对其进行分析。
关于Java - 静态 block 和线程同步问题 - 一个案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15048971/