views:

286

answers:

2

I have a Java class that extends Thread, it basically looks like the following:

public class HttpRequestDispatcher extends Thread {
    private String url;
    private String method; // GET or POST
    private byte[] postData;

    public HttpRequestDispatcher(String url, String method, byte[] postData) {
        this.url = url;
        this.method = method;
        this.postData = postData;
    }

    public HttpRequestDispatcher(String url, String method) {
        this.url = url;
        this.method = method;
    }

    public void run() {
        ...
    }
}

I need the run() method to return a ByteArrayOutputStream or a String. However, because it is in the run() method of the Thread, I cannot set the return type of the method to a ByteArrayOutputStream or a String.

The HttpRequestDispatcher class is called inside of a class called OAuth.java.

How can I get around this situation?

+3  A: 

There are several solutions to this problem:

  • Use an data structure external to the Thread. Pass the object in your constructor and update it, when your Thread is about to finish.

  • Use a callback method. When your Thread finishes, call the callback.

  • Make use of a java.util.concurrent.Future (Java >= 1.5):

    A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.

The MYYN
With the callback method approach: The Thread will finish when the HttpRequest succeeds or fails. So let's say that I have two methods: requestSucceeded and requestFailed. The thread will call either one of those methods, depending on its result. My one question from there is how can I return the results of requestSucceeded or requestFailed back to the original method in OAuth.java which originally started the Thread? Thanks!
behrk2
You could, e.g., define your callbacks in OAuth.java. Pass the OAuth object down to the Thread. Then, depending on the result, call the appropriate callback. The callback function could accept 'the sender' as one of the parameters, if you need to dispatch multiple Threads to different actions. That's just an idea ..
The MYYN
+1  A: 

Let it implement Callable<T> instead of Thread or Runnable. Here T must represent the type of the result. Use ExecutorService to execute it. It will return the result in flavor of a Future<V>.

Here's an SSCCE with String as T, just copy'n'paste'n'run it.

package com.stackoverflow.q2300433;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Test {
    public static void main(String... args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new Task());
        System.out.println(future.get()); // Prints "result" after 2 secs.

        // Or if you have multiple tasks.
        // List<Future<String>> futures = executor.invokeAll(Arrays.asList(new Task()));
        // for (Future<String> future : futures) {
        //     System.out.println(future.get());
        // }

        executor.shutdown(); // Important!
    }
}

class Task implements Callable<String> {
    public String call() throws Exception {
        Thread.sleep(2000);
        return "result";
    }
}
BalusC
I'm planning to try out this approach. If you look at my comment on the below post, you will see that there are two cases in which the Thread will finish...it will succeed and return a ByteArrayOutputStream, or it will fail and return a stream. Is this a good method for accepting different types of objects? I am looking for versatility - there are going to be a lot of different classes using this HttpRequestDispatcher
behrk2
Make it abstract and name it `HttpResponse`. It will become more straightforward.
BalusC