Java Vector <E>блокируется без видимой причины - PullRequest
0 голосов
/ 15 декабря 2010

Я, вероятно, что-то делаю не так, но вот что происходит:

Я регистрирую слушателя, жду, когда он будет вызван, и когда он выполнит и вызовет 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 Ответ

3 голосов
/ 15 декабря 2010

Ваш конструктор устанавливает локальную переменную с именем output, а не переменную-член, у вас есть

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

когда это должно быть

output = new Vector<Entry>();

Итак, позже при вызове output.clear() выдается исключение Null Pointer Exception, поэтому следующие строки кода не выполняются.

Предупреждения компилятора, такие как "неиспользуемые локальные переменные", могут помочь обнаружить такие ошибки.

...