3 Stimmen

Rückgabewert eines Threads

Ich habe unten eine Thread-Klasse, die eine Datei von einer URL liest und das Ergebnis dann in einer öffentlichen statischen Variable speichert, damit sie von anderen Klassen abgerufen werden kann. Gibt es eine bessere Möglichkeit, dies zu erreichen?

Danke

public class ReadContent implements Runnable{

    private HttpConnection connection;
    private InputStream inputStream;
    private String url;

    public ReadContent(String url){
        this.url = url;
    }

    public void run() {
        readContentURL();
    }

    private void readContentURL() {

        try {   
                connection = (HttpConnection)Connector.open(url);
                connection.setRequestMethod(HttpConnection.GET);
                connection.setRequestProperty("Connection", "close");
                inputStream = connection.openDataInputStream();

            //  inputStream = getClass().getResourceAsStream(url);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int c ;
                while (true) {
                    c = inputStream.read();
                    if (c == -1)
                        break;
                    baos.write(c);
                }

                SavedJSON.result = new JSONObject(new String(baos.toByteArray()));

            } 
            catch(Exception e){
                e.printStackTrace();
            }   
    }

}

Hier ist meine vorgeschlagene Lösung -

public class MyFuture{ 
      private final Object lock = new Object();

      private JSONObject value;
      public void set(JSONObject t){
          value = t;
          synchronized(lock){
              value = t;
              lock.notifyAll();  
          }
      }

      public JSONObject get(){
         synchronized(lock){
              while(value == null)
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

              return value;
         }

      }    
    }

public class SavedJSON {

    public static MyFuture result;
    }

public class ReadContent implements Runnable{

    private HttpConnection connection;
    private InputStream inputStream;
    private String url;

    public ReadContent(String url){
        this.url = url;
    }

    public void run() {
        readContentURL();
    }

    private void readContentURL() {

        try {   
            int len = 0;
                connection = (HttpConnection)Connector.open(url);
                connection.setRequestMethod(HttpConnection.GET);
            //  connection.setRequestProperty("Connection", "close");
                inputStream = connection.openDataInputStream();

            //  inputStream = getClass().getResourceAsStream(url);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int c ;
                while (true) {
                    c = inputStream.read();
                    if (c == -1)
                        break;
                    ++len;
                    baos.write(c);
                }

                SavedJSON.result.set(new JSONObject(new String(baos.toByteArray(), 0, len, "utf-8")));

            } 
            catch(Exception e){
                e.printStackTrace();
            }   
    }

}

2voto

John Vint Punkte 38604

Da Sie kein Callable verwenden können (und ich gehe davon aus, dass Sie auch kein Future verwenden können), können Sie versuchen, Ihr eigenes Future zu erstellen. Es ist relativ einfach:

public class MyFuture{ // Können Sie auch Generics nicht verwenden?
  private final Object lock = new Object();

  private T value;
  public void set(T t){
      synchronized(lock){
          value = t;
          lock.notifyAll();  
      }
  }
  public T get(){
     synchronized(lock){
          while(value == null) lock.wait();

          return value;
     }

  }    
}

Jetzt können Sie SavedJSON.result zu einem MyFuture machen und wann immer jemand den Wert benötigt und warten muss, kann er einfach SavedJSON.result.get() aufrufen; und das Setzen kann natürlich SavedJSON.result.set(new JSONObject(new String(baos.toByteArray()))); sein

Bearbeitung:

Dies dient dazu, auf Ihren Kommentar und Ihre Bearbeitung einzugehen.

Erstens: Möglicherweise möchten Sie die unterbrochene Ausnahme weitergeben. Gewöhnlich versuchen Threads, andere Threads mit Hilfe von Unterbrechungen zu 'stoppen'. Sie können entweder eine throws-Deklaration auf der Methode hinzufügen, eine Laufzeit-Ausnahme werfen oder einfach einen Nullwert zurückgeben.

Zweitens: Sie sollten value = t nicht außerhalb des synchronisierten Blocks haben. Aus verschiedenen Gründen kann dies fehlschlagen. Sie sollten diese Zeile entfernen und dann sieht es ziemlich gut aus.

1voto

Sanjay T. Sharma Punkte 22330

Schauen Sie sich das Callable-Interface (für ein Runnable, das einen Wert zurückgibt) und die Executors-Klasse für verschiedene Implementierungen von Thread-Pools an.

1voto

Adriano Punkte 73

Für deinen Fall schlage ich vor, einen Rückruf zu implementieren, wie zum Beispiel:

Rückruf:

public interface SimpleCallback {
    public void onReceive(JSONObject data);
}

Aufrufer:

...
SimpleCallback callback = new SimpleCallback() { 
    public void onReceive(JSONObject data) {
        // etwas tun
    }
}
new Thread(new ReadContent(url, callback));
...

Thread:

...
    // Eingabestrom lesen
    callback.onReceive(new JSONObject(new String(baos.toByteArray())));
} catch(Exception e){
...

Ich hoffe, das hilft.

0voto

duselbaer Punkte 935

Vielleicht sollten Sie sich das Konzept der Futures ansehen.

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html

0voto

Vladimir Ivanov Punkte 42019

Ihr Ergebnis ist nicht synchronisiert. Sie sollten Ihre SavedJSON-Klasse verbessern, um die getResult() und setResult() Methoden zu erstellen und diese synchronisiert zu machen. Die wait() und notify() Methoden sollten Ihnen auch helfen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X