Call and pass parameter to method in another thread

Arya :

I have created this small project to show what I want to do, but in reality it will be used in a large application which uses about 60 different threads.

I have two classes

public class Main {

    public static void main(String[] args) {
        Http http = new Http();
        Thread threadHttp = new Thread(http, "httpThread1");
        threadHttp.start();

        http.getPage("http://google.com"); // <-- This gets called on 
                                           // the main thread, 
                                           //I want it to get called from the
                                            // "httpThread1" thread
    }
}

and

public class Http implements Runnable {
    volatile OkHttpClient client;

    @Override
    public void run() {
        client = new OkHttpClient.Builder().readTimeout(10, TimeUnit.SECONDS).retryOnConnectionFailure(true).build();

    }

    public void getPage(String url) {
        Request request = new Request.Builder().url(url).build();

        try {
            Response response = client.newCall(request).execute();
            System.out.println(response.body().string());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

From the main thread, I want to be able to call the getPage method but have it execute on the httpThread1 that we started and initialized OkHttpClient client

Is this possible? how can it be done?

ernest_k :

Runnable#run is the method designed to do the actual work of a Runnable object. So you would have to make it do what you're currently doing in getPage.

You can use state to store url, and save the response in a different field. See further comments about how you can refactor this to simplify it even further. But from the current code, the simplest changes could be:

class Http implements Runnable {

    //initialize Http. This can be done better perhaps
    volatile OkHttpClient client = new OkHttpClient.Builder()
            .readTimeout(10, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true).build();

    private Response response;

    private String url;

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

    @Override
    public void run() {
        this.getPage(this.url);
    }

    public void getPage(String url) {
        Request request = new Request.Builder().url(url).build();

        try {
            this.response = client.newCall(request).execute();
            System.out.println(response.body().string());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

And in your main method:

Http http = new Http("http://google.com");
Thread threadHttp = new Thread(http, "httpThread1");
threadHttp.start();
threadHttp.join();
Response resp = http.getResponse();

However, this can be substantially simplified with the use of futures. For example, it could look as simple as:

class Http {
    volatile OkHttpClient client = new OkHttpClient.Builder()
            .readTimeout(10, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true).build();

    public Response getPage(String url) {
        Request request = new Request.Builder().url(url).build();

        try {
            this.response = client.newCall(request).execute();
            System.out.println(response.body().string());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

And, using futures, your main method can look even simpler:

public static void main(String[] args) throws Exception {
    Http http = new Http();
    CompletableFuture<Response> future = 
            CompletableFuture.supplyAsync(() -> http.getPage("http://google.com"));

    //the preceding statement will call `getPage` on a different thread.
    //So you can do other things before blocking with next statement

    Response resp = future.join();
}

You can even use a thread pool with supplyAsync if you need more control over how asynchronous tasks run.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=106662&siteId=1