Java Vector <e>被阻止,没有明显的原因</e>

时间:2010-12-14 23:14:42

标签: java blocking jxta

我可能做错了什么,但这就是发生的事情:

我注册一个监听器,等待它被调用,当它执行并调用“Vector.clear()”时它会锁定。问题发生在“pipeMsgEvent”方法中,这里是不太友好的代码(如果你愿意,直接转到“这是重要的”行):

public class JxtaCustomer implements PipeMsgListener {
    public static final int ANSWER_OK        = 0;
    public static final int ANSWER_TIMEOUT   =-1;
    public static final int ANSWER_NOT_ASKED =-2;
    public static final int ANSWER_WORKING   =-3;

    public static final int REQ_SENT         = 0;
    public static final int REQ_INV_PIPE_ID  =-1;
    public static final int REQ_INV_PIPE_IO  =-2;
    public static final int REQ_INV_GROUP_ID =-3;

    protected int answer;

    protected JxtaGenericAdvertisement serviceAdv = null;
    protected JxtaNode ThePeer = null;

    JxtaBiDiPipe myBiDiPipe = null;
    protected Vector<Entry> output = null;

    public JxtaCustomer(JxtaGenericAdvertisement adv, JxtaNode peer)
    {
        ThePeer = peer;
        serviceAdv = new JxtaGenericAdvertisement((Element)adv.getDocument(new MimeMediaType("text/xml")));

        answer = ANSWER_NOT_ASKED;
        Vector<Entry> output = new Vector<Entry>();
    }

    public void pipeMsgEvent(PipeMsgEvent event)
    {
        System.out.println("It Works! Uhuuu");
        // We received a message
        Message message = event.getMessage();

        System.out.println("Lets GO! Uhuuu");
        Message.ElementIterator elIt = message.getMessageElementsOfNamespace( serviceAdv.getName() );

        System.out.println("A little bit more");
        answer = ANSWER_WORKING;

        System.out.println("enter");

        // This is important: Here I get stuck, "clear"
        // never appears on the screen
        output.clear();
        System.out.println("clear");
        while (elIt.hasNext()) {
            MessageElement mElem = elIt.next();
            System.out.println(mElem.getElementName() + " " + mElem.toString());
            output.add( new Entry( mElem.getElementName(), mElem.toString() ) );
        }
        System.out.println("leave");

        answer = ANSWER_OK;
    }

    public int sendRequest(Vector<Entry> params)
    {
        try {

            // Creating Pipe Advertisement
            String pipeAdvType = PipeAdvertisement.getAdvertisementType();
            PipeAdvertisement pipeAd = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(pipeAdvType);

            URI pipeURI = new URI(serviceAdv.getPipeID());
            pipeAd.setPipeID( IDFactory.fromURI(pipeURI) );
            pipeAd.setType(PipeService.UnicastType);
            pipeAd.setName(serviceAdv.getName() + " Service Pipe");
            pipeAd.setDescription("Created by " + serviceAdv.getName());

            // Creating Group
            JxtaGroup jxgp = ThePeer.getGroupFromID( serviceAdv.getGroupID() );
            if (null == jxgp)
                return REQ_INV_GROUP_ID;

            PeerGroup group = jxgp.getPeerGroup();
            if (null == group)
                return REQ_INV_GROUP_ID;

            // This is important: In the JxtaBiDiPipe call I register
            // the callback, while I have access to the code, I think
            // the problem is in my code
            myBiDiPipe = new JxtaBiDiPipe( group, pipeAd, 30000, this);

            if (myBiDiPipe.isBound()) {
                Thread.sleep(500);

                Message myMessage = new Message();

                if (0 == params.size())
                    params.add( new Entry("dummy", "null") );

                for (int i=0; i<params.size(); i++) {
                    String Key = params.get(i).getKey();
                    String Value = params.get(i).getValue();
                    StringMessageElement strMsgElem = new StringMessageElement( Key, Value, null);
                    myMessage.addMessageElement( serviceAdv.getName(), strMsgElem);
                }

                myBiDiPipe.sendMessage(myMessage);

                answer = ANSWER_TIMEOUT;

                return REQ_SENT;
            }
        } catch (URISyntaxException e){
            e.printStackTrace();

            return REQ_INV_PIPE_ID;
        } catch (IOException e) {
            return REQ_INV_PIPE_IO;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return REQ_INV_PIPE_IO;
    }

    public Vector<Entry> getResponse()
    {
        Vector<Entry> results = new Vector<Entry>();

        if (ANSWER_OK != answer)
            return results;

        // This is important: I always call "getState()" and check its value
        // before calling this method, so you can say it's guaranteed to be
        // called after answer = ANSWER_OK, which never happens because of the
        // lock
        for (int i=0; i<output.size(); i++)
            results.add( output.get(i) );

        return results;
    }

    public int getState()
    {
        int count = 10;

        return answer;
    }
}

我总是像这样创建JxtaCustomer:

JxtaCustomer customer = new JxtaCustomer(adv, ThePeer);
Vector<Entry> params = new Vector<Entry>();

params.add( new Entry("key1", "value1") );
params.add( new Entry("key2", "value2") );

customer.sendRequest(params);

while(JxtaCustomer.ANSWER_OK != customer.getState()) {
   // I was actually using synchronized locks and timed waits
   // but since I'm stuck there I'm using this nonsense instead
}

Vector<Entry> response = customer.getResponse();

这里是代码中我称之为“睡眠”,“等待”或我创建“同步”(最后一个永远不会)的地方

$ grep synchronized $(find . -name "*.java")

$ grep sleep $(find . -name "*.java")
./Src/net/ubi/jxta/JxtaCustomer.java:                Thread.sleep(500);

$ grep wait $(find . -name "*.java")
./App/ExampleServices/SimpleSigner.java:    boolean waiting = false;
./App/ExampleServices/SimpleSigner.java:        waiting = true;
./App/ExampleServices/SimpleSigner.java:        return (waiting && JxtaCustomer.ANSWER_OK == customer.getState());
./App/ExampleServices/SimpleSigner.java:        if (!waiting)
./App/ExampleServices/SimpleSigner.java:            waiting = false;
./App/ExampleServices/SimpleSigner.java:            return "Error: Response not ready, wait more time\n";

1 个答案:

答案 0 :(得分:3)

你的构造函数设置一个名为output的局部变量,而不是成员变量,你有

Vector<Entry> output = new Vector<Entry>();

什么时候应该

output = new Vector<Entry>();

所以,稍后当你调用output.clear()时,你会得到一个Null Pointer Exception,这就是为什么下面的代码行没有被执行。

像“未使用的局部变量”这样的编译器警告可以帮助发现这些类型的错误。