Search code examples
javahttpthread-safetyinterrupt

How can i gracefully interrupt a stream from HTTP in Java?


I'm running a Java code that listen to a long polling HTTP stream. This is the method I'm using.

void connectStream() throws IOException, URISyntaxException {

    URIBuilder uriBuilder = new URIBuilder("...");

    HttpGet httpGet = new HttpGet(uriBuilder.build());
    HttpResponse response = httpClient.execute(httpGet);
    HttpEntity entity = response.getEntity();
    if (null != entity) {
        InputStreamReader stream = new InputStreamReader((entity.getContent()));
        BufferedReader reader = new BufferedReader(stream);
        String line;
        while ((line = reader.readLine()) != null) {
            // do stuff
        }
    }
}

I need to interrupt gracefully this stream from the main thread. What is the best way to do it? For now, I'm adding an AtomicBoolean variable and check it in each iteration of the loop.

private AtomicBoolean interrupt = new AtomicBoolean(false);

void connectStream() throws IOException, URISyntaxException {

    URIBuilder uriBuilder = new URIBuilder("...");

    HttpGet httpGet = new HttpGet(uriBuilder.build());
    HttpResponse response = httpClient.execute(httpGet);
    HttpEntity entity = response.getEntity();
    if (null != entity) {
        InputStreamReader stream = new InputStreamReader((entity.getContent()));
        BufferedReader reader = new BufferedReader(stream);
        String line;
        while ((line = reader.readLine()) != null) {
            if (interrupt.get()) {
                break;
            }
            // do stuff
        }
    }
}

public void setInterrupt() {
    this.interrupt.set(true);
}

This works well when the buffer often contains data. But what if the buffer remains empty for a long time?

I've already tried to close stream and reader: the program does not execute the code inside the loop any more it does not exit from it.


Solution

  • Solved! I could find a way to get the socket underlying the HTTP connection. By closing it, the thread quits correctly.

    // No need this anymore
    // private AtomicBoolean interrupt = new AtomicBoolean(false);
    
    // New
    private Socket socket;
    
    void connectStream() throws IOException, URISyntaxException {
    
        URIBuilder uriBuilder = new URIBuilder("...");
    
        HttpGet httpGet = new HttpGet(uriBuilder.build());
    
        // New block code here
        HttpClientContext context = HttpClientContext.create();
        HttpResponse response = httpClient.execute(httpGet, context);
        ManagedHttpClientConnection connection = context.getConnection(ManagedHttpClientConnection.class);
        socket = connection.getSocket();
    
        HttpEntity entity = response.getEntity();
        if (null != entity) {
            InputStreamReader stream = new InputStreamReader((entity.getContent()));
            BufferedReader reader = new BufferedReader(stream);
            String line;
            while ((line = reader.readLine()) != null) {
                // do stuff
            }
        }
    }
    
    public void setInterrupt() {
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }