java.lang.InterruptedException с использованием swingworker

Я использую Swingworker для запроса значения с URL-адреса для динамического изменения версии отображаемой информации. В некоторых случаях этот рабочий отменяется. Проблема в том, что я иногда получаю java.lang.InterruptedException (но не каждый раз, когда отменяю worker). Я не уверен, что с ним делать, более того, я понятия не имею, куда он брошен, я не могу отладить его, потому что получаю его, когда делаю много изменений версии за короткое время (я использую ползунок, и это происходит, когда я перетаскиваю его на некоторое время) . Все работает нормально, но я получаю досадную ошибку:

 java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at sun.plugin2.message.Queue.waitForMessage(Unknown Source)
at sun.plugin2.message.Pipe$2.run(Unknown Source)
at com.sun.deploy.util.Waiter$1.wait(Unknown Source)
at com.sun.deploy.util.Waiter.runAndWait(Unknown Source)
at sun.plugin2.message.Pipe.receive(Unknown Source)
at sun.plugin2.main.client.MessagePassingExecutionContext.doCookieOp(Unknown Source)
at sun.plugin2.main.client.MessagePassingExecutionContext.getCookie(Unknown Source)
at sun.plugin2.main.client.PluginCookieSelector.getCookieFromBrowser(Unknown Source)
at com.sun.deploy.net.cookie.DeployCookieSelector.getCookieInfo(Unknown Source)
at com.sun.deploy.net.cookie.DeployCookieSelector.get(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.setCookieHeader(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.writeRequests(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at org.dbwiki.web.applet.ValueRequester.doInBackground(ValueRequester.java:40)
at org.dbwiki.web.applet.ValueRequester.doInBackground(ValueRequester.java:1)
at javax.swing.SwingWorker$1.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at javax.swing.SwingWorker.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Также после каждого исключения, которое показано выше, выдается дополнительное сообщение:

sun.plugin2.main.client.PluginMain: unrecognized message ID 46

Интересно, что исключение выдается только тогда, когда программа запускается в браузере как апплет, если программа запускается как апплет из api, никаких исключений не возникает.

Мой StringWorker:

    package org.dbwiki.web.applet;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import javax.swing.SwingWorker;

public class ValueRequester extends SwingWorker<Void, Void> {
    HtmlGenerator htmlGen;
    ArrayList<String[]> versionsData;
    String id;
    private String dbName;
    ValueRequester (HtmlGenerator htmlGen, ArrayList<String[]> versionData, int ver){
    try {
        this.htmlGen=htmlGen;
        if (TreeVisualiser.typeParameter.equals(TreeVisualiser.StructureVisualiserParameter))
            this.id=htmlGen.getElem().getVersionElementId(ver);
        else if(TreeVisualiser.typeParameter.equals(TreeVisualiser.HistoryVisualiserParameter))
            this.id=htmlGen.getElem().getId();
        this.dbName=htmlGen.getElem().getDBName();
        this.versionsData=versionData;
    } catch (Exception e) {
        e.printStackTrace();
    }

    }
    protected Void doInBackground() throws Exception {
    try{
        String value="";
        URL historyURL = new URL("http://127.0.0.1:8080/"+dbName+id+"?value");
        URLConnection hc = historyURL.openConnection();     
        BufferedReader in = new BufferedReader(new InputStreamReader(hc.getInputStream()));  
        String line;
        while ((line = in.readLine()) != null) {
            value+=line;
        }
        in.close();

        this.htmlGen.formDisplayerHead();
        this.htmlGen.formNodeDataHtml(value,this.versionsData);
        this.htmlGen.formDisplayerTail();
    }   
    catch(Exception e)
    {
        e.printStackTrace();
    }
        return null;
}

protected void done()
{
    if (!this.isCancelled())
    this.htmlGen.dataDisplayer.setText(this.htmlGen.getHtml());

}

}

Теперь я знаю, чем это вызвано, как с этим справиться или, по крайней мере, как скрыть (так как все работает нормально). Любая помощь будет оценена по достоинству.

ОБНОВЛЕНИЕ:

Я пытаюсь перехватить это исключение в ValueRequester.doInBackround (), однако мой оператор catch не перехватывает исключение. Мой обновленный код doInBackground ():

protected Void doInBackground() throws Exception {
       try{
          String value="";
            URL historyURL = new URL("http://127.0.0.1:8080/"+dbName+id+"?value");

            URLConnection hc = historyURL.openConnection(); 
            InputStream inputStrm=hc.getInputStream();
           InputStreamReader inputStrmRdr= new InputStreamReader(inputStrm);
            this.in = new BufferedReader(inputStrmRdr);  
            String line;
            while ((line = in.readLine()) != null) {
                value+=line;
            }
            this.htmlGen.formDisplayerHead();
            this.htmlGen.formNodeDataHtml(value,this.versionsData);
            this.htmlGen.formDisplayerTail();
       }catch (InterruptedException e){
           System.out.println("Interrupted Exception caught!");
          // e.printStackTrace();
       }

    return null;
}

К сожалению, трассировка стека по-прежнему печатается вместо сообщения о выходе из системы. Есть идеи, что здесь может быть не так?


person M T    schedule 05.07.2012    source источник
comment
Это ведь не полная трассировка стека? На самом деле вы получаете исключение IOException, вызванное этим InterrupedException, верно?   -  person JB Nizet    schedule 05.07.2012


Ответы (2)


Насколько мне известно, InterruptedException возникает только в том случае, если какой-то другой поток вызывает Thread.interrupt() в потоке, который заблокирован. В этом случае очевидно, что прерванный поток в это время выполнял wait() вызов.

Глядя на код SwingWorker, кажется, что рабочий поток получит прерывание, если запланированный поток решит вызвать cancel(true) на нем. В зависимости от того, что рабочий поток делает в данный момент, он может получить InterruptedException или просто установить флаг Thread.interrupted.

Таким образом, решение вашей проблемы, по-видимому, состоит в том, чтобы выяснить, что вызывает cancel(true) в экземпляре SwingWorker. Затем либо измените его, чтобы не делать этого ... либо заставьте ваш рабочий класс работать с InterruptedException соответствующим образом. Подходящим поведением, вероятно, будет перехват исключения и тихий возврат из call(...)

person Stephen C    schedule 05.07.2012
comment
даже я удалил здесь свой пост Я думаю, что возвращает только get () исключения, а не так, как вы описали only occurs if some other thread calls, общая проблема заключается в том, что все, что вызывается из SwingWorker, не возвращает исключения напрямую - person mKorbel; 05.07.2012
comment
@mKorbel - Я знаю, о чем вы говорите, и в некотором смысле вы правы. Но вопрос НЕ об исключениях, которые выдает get(). Посмотрите на трассировку стека. - person Stephen C; 05.07.2012
comment
согласен, аааааааааааааааааааааааааааааааае более рядом, это возможно только при создании нового объекта в качестве локальной переменной, возможно, это была неправильная идея / ошибка при создании этих объектов внутри SwingWorker (объект мог быть создан раньше) или вообще использовать SwingWorker для этого типа фона задания - person mKorbel; 05.07.2012
comment
Да, экземпляр иногда отменяется с помощью метода cancel (true). Это необходимо в некоторых случаях. Однако я не уверен, где поймать это исключение. Я пытался окружить функции cancel (), execute () и doInBackground () и поймать это исключение, но ничего не работает. Я абсолютно новичок в программировании потоков, так что извините меня, если часть моей логики не имеет особого смысла или я упускаю что-то действительно очевидное. - person M T; 05.07.2012
comment
Вы должны поймать его в ValueRequester.doInBackground или call методе анонимного класса, который вы используете для вызова doInBackground. - person Stephen C; 05.07.2012

Для меня это просто выглядит так, как будто вы звоните worker.cancel(true); (при условии, что worker - это ваш SwingWorker). true указывает, что если текущий поток находится в состоянии прерывания, поток может быть прерван. Когда это происходит, он автоматически генерирует исключение, указывающее, что поток был прерван, что позволяет вам освободить ресурсы и, возможно, что-то сделать. Думаю, в вашем случае вы можете спокойно игнорировать это и просто закрыть открытые потоки.

В вашем случае, в зависимости от того, как далеко вы продвинулись в своей «Работе», задача может быть прервана или нет.

См. Дополнительную информацию о прерывании потока здесь.

person Guillaume Polet    schedule 05.07.2012