什么是要做?


从此处下载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被阻止(可能正在等待对方)

我的分析:


DataSMOutbind类都有一个共同的祖先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中提供的工厂方法创建其子对象,例如DataSMOutbindcreatePDU等。


因此,当我的测试应用程序执行时,一个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;
}

DataSMOutbind和其他PDU子类的构造函数做什么?
除了初始化一些实例变量外,什么都没有。这些是POJO。它们不保留任何外部资源,例如文件,数据库等。

最佳答案

您的线程可能正在阻塞,但并非出于您的考虑原因。静态初始化程序在加载类时执行,而不是在创建实例时执行。因此,您不必让两个对象“进入”静态初始值设定项,并在某个时候陷入某个共享变量的死锁状态。

在不知道所用库的确切细节的情况下,很难诊断出真正的问题是什么,但是我建议您转储线程并使用一个不错的工具对其进行分析。


How to Take a Thread Dump
Thread Dump Analysis Tool

关于java - Java-静态块和线程同步问题-现有案例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15048971/

10-10 17:13