How to cancel a thread making a http request from another thread
The thread that made the request is blocked while waiting the server to respond. If you take a thread dump and see, it will be in some read() method, but not on a Thread.sleep. So calling interrupt() will not have an effect (unless it's an InterruptibleChannel).Do you have access to the socket or the output stream on which the POST request was made? If so, you can close that, which will bring out of the read wait with an exception.Do you have a code sample that you can put up?
Helloo everyone, finally got this closing socket idea implemented and working. below is the snippet i tried.
my Requesting thread
package com.pkg.myhttptest;import org.apache.http.client.methods.HttpPost;public class RequestThread implements Runnable{ Message msg = null; Util util = null; public RequestThread(Message msg, Util util) { this.msg = msg; this.util = util; } public void run() { System.out.println("its request thread"); util.print(msg); }}
Cancelling Thread
public class CancelThread implements Runnable { Message msg = null; Util util = null; public CancelThread(Message msg, Util util) { this.msg = msg; this.util = util; } public void run() { System.out.println("its cancel thread"); int i=0; while(i<5){ System.out.println("looping" + i); i++; } System.out.println(msg.getHttpost() + "In cancelled"); Header[] hdr = msg.getHttpost().getAllHeaders(); System.out.println(hdr.length + "length"); msg.getHttpost().abort(); System.out.println(msg.getHttpost().isAborted()); }}
Shared Object
public class Message { HttpPost httpost; public HttpPost getHttpost() { return httpost; } public void setHttpost(HttpPost httpost) { this.httpost = httpost; }}
Util Class
public class Util { private final String USER_AGENT = "Mozilla/5.0"; public void print(Message msg) { String url = "https://selfsolve.apple.com/wcResults.do"; HttpPost post = new HttpPost(url); HttpClient client = HttpClientBuilder.create().build(); post.setHeader("User-Agent", USER_AGENT); List<NameValuePair> urlParameters = new ArrayList<NameValuePair>(); urlParameters.add(new BasicNameValuePair("sn", "C02G8416DRJM")); urlParameters.add(new BasicNameValuePair("cn", "")); urlParameters.add(new BasicNameValuePair("locale", "")); urlParameters.add(new BasicNameValuePair("caller", "")); urlParameters.add(new BasicNameValuePair("num", "12345")); try { post.setEntity(new UrlEncodedFormEntity(urlParameters)); msg.setHttpost(post); HttpResponse response = client.execute(post); System.out.println("Response Code : " + response.getStatusLine().getStatusCode()); BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); StringBuffer result = new StringBuffer(); String line = ""; while ((line = rd.readLine()) != null) { result.append(line); } } catch (UnsupportedEncodingException e) { } catch (IOException e) { e.printStackTrace() } }
Main Class
public class App { public static void main( String[] args ) { Message msg = new Message(); Util util = new Util(); Thread reqThread = new Thread(new RequestThread(msg, util)); Thread cancelThread = new Thread(new CancelThread(msg, util)); System.out.println("Starting Threads"); reqThread.start(); try { reqThread.sleep(2000); cancelThread.start(); cancelThread.join(); System.out.println("closing.."); } catch (InterruptedException e) { e.printStackTrace(); } }}
Its little uncleaned code I agree, but it works. It results in below exception and kills the thread.
java.net.SocketException: Socket is closed at java.net.Socket.getInputStream(Socket.java:876) at sun.security.ssl.SSLSocketImpl.doneConnect(SSLSocketImpl.java:644) at sun.security.ssl.SSLSocketImpl.<init>(SSLSocketImpl.java:549)
Thanks everyone who has put their efforts in helping me.
I was trying to solve the same thing. I wrote an HTTP Request Runnable that took 20 seconds to timeout and executed on one thread (1st Thread). I wrote a Timeout Runnable on a separate thread (2nd Thread) that was supposed to interrupt/stop the 1st Thread after 10 seconds. For every second in the Main Thread (3 threads total), I printed the state of the threads and found the 1st thread kept running.
import java.util.Collections;import java.util.LinkedHashMap;import java.util.Map;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.util.EntityUtils;public class A_Test_Thread_Interrupt { public static final String URL_THAT_CAUSES_CONNECTION_TIMED_OUT_AFTER_20_SECONDS = "https://..."; // Need to provide this for your system. Must timeout after 20 seconds// java.net.ConnectException: Connection timed out: connect// at java.net.DualStackPlainSocketImpl.connect0(Native Method)// at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)// at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)// at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)// at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)// at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)// at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)// at java.net.Socket.connect(Socket.java:589)// at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:542)// at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:414)// at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)// at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:326)// at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:610)// at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:445)// at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835)// at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)// at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)// at A_Test_Thread_Interrupt$HttpRequestRunnable.run(A_Test_Thread_Interrupt.java:35)// at java.lang.Thread.run(Thread.java:748) public static void main(String[] args) { System.out.println("main Start"); long startTime = System.currentTimeMillis(); SharedData sd = new SharedData(); System.out.println("Starting HTTPS Request Thread"); HttpRequestRunnable httpRequestRunnable = new HttpRequestRunnable(sd); Thread workerThread = new Thread(httpRequestRunnable); workerThread.start();// workerThread.stop(); System.out.println("Starting Timeout Thread"); TimeoutRunnable timeoutRunnable = new TimeoutRunnable(workerThread, httpRequestRunnable, sd); Thread timeoutThread = new Thread(timeoutRunnable); timeoutThread.start(); for(int i=0; i<30; i++) { System.out.println("workerThread.getState():"+workerThread.getState()+" timeoutThread.getState():"+timeoutThread.getState()); try { // Sleep for 1 second Thread.sleep(1*1000); } catch (Exception ex) { ex.printStackTrace(); } } long endTime = System.currentTimeMillis(); System.out.println("main End timeInSeconds:"+(endTime-startTime)/1000); } public static class HttpRequestRunnable implements Runnable { SharedData sharedData; public HttpRequestRunnable (SharedData sharedData) { this.sharedData = sharedData; sharedData.setIsFinished(this, false); } public void run() { System.out.println("Running HttpRequestRunnable Runner Start"); long startTime = System.currentTimeMillis(); try { HttpGet httpGet = new HttpGet(URL_THAT_CAUSES_CONNECTION_TIMED_OUT_AFTER_20_SECONDS); CloseableHttpResponse response = new DefaultHttpClient().execute(httpGet); String responseString = EntityUtils.toString(response.getEntity()); System.out.println("responseString:"+responseString); sharedData.setIsFinished(this, true); } catch (Exception ex) { ex.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println("Running HttpRequestRunnable Runner End timeInSeconds:"+(endTime-startTime)/1000); } } public static class SharedData { Map<Runnable, Boolean> isFinishedMap = Collections.synchronizedMap(new LinkedHashMap<Runnable, Boolean>()); public void setIsFinished(Runnable runnable, Boolean value) { synchronized(isFinishedMap) { isFinishedMap.put(runnable, value); } } public Boolean getIsFinished(Runnable runnable) { synchronized(isFinishedMap) { return isFinishedMap.get(runnable); } } } public static class TimeoutRunnable implements Runnable { Thread workerThreadToKillIfItTakesTooLong; Runnable runnable; SharedData sharedData; public TimeoutRunnable(Thread workerThreadToKillIfItTakesTooLong, Runnable runnable, SharedData sharedData) { this.workerThreadToKillIfItTakesTooLong = workerThreadToKillIfItTakesTooLong; this.runnable = runnable; this.sharedData = sharedData; } public void run() { System.out.println("Running TimeoutRunnable Runnable Start"); long startTime = System.currentTimeMillis(); int secondsToSleep = 1; int iterationsPerNote = 2; int iterations = 10; for(int i=0; i<iterations; i++) { // Sleep for at most 10 seconds boolean workerRunnableIsFinished = sharedData.getIsFinished(runnable); if(workerRunnableIsFinished) { return; } else { if(i % iterationsPerNote == 0) { // Print a message every 2 iterations System.out.println("TimeoutRunnable waiting for workerRunnable..."); } } try { // Sleep for 1 second Thread.sleep(secondsToSleep*1000); } catch (Exception ex) { ex.printStackTrace(); } } // 5 minutes have passed, kill thread System.out.println("Killing worker thread for taking too long"); workerThreadToKillIfItTakesTooLong.stop(); sharedData.setIsFinished(runnable, true); long endTime = System.currentTimeMillis(); System.out.println("Running TimeoutRunnable Runnable End timeInSeconds:"+(endTime-startTime)/1000); } }}
Here was the output
main: main Startmain: Starting HTTPS Request Threadmain: Starting Timeout Thread1st_: Running HttpRequestRunnable Runner Startmain: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: Running TimeoutRunnable Runnable Start2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLEmain: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLEmain: workerThread.getState():RUNNABLE timeoutThread.getState():TIMED_WAITING2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLEmain: workerThread.getState():RUNNABLE timeoutThread.getState():TIMED_WAITING2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLEmain: workerThread.getState():RUNNABLE timeoutThread.getState():TIMED_WAITING2nd_: Killing worker thread for taking too longmain: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: Running TimeoutRunnable Runnable End timeInSeconds:10main: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():RUNNABLE timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: main End timeInSeconds:30
I use a SharedData class to hold information needed by both threads. By adding the extra information needed to terminate the thread (ie the HttpGet), I can have the monitoring thread do whatever is necessary to actually terminate the thread (ie call httpGet.abort). This is the modified code (modified lines end with // MOD)
import java.util.Collections;import java.util.LinkedHashMap;import java.util.Map;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.util.EntityUtils;public class A_Test_Thread_Interrupt { public static final String public static final String URL_THAT_CAUSES_CONNECTION_TIMED_OUT_AFTER_20_SECONDS = "https://..."; // Need to provide this for your system. Must timeout after 20 seconds// java.net.ConnectException: Connection timed out: connect// at java.net.DualStackPlainSocketImpl.connect0(Native Method)// at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)// at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)// at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)// at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)// at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)// at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)// at java.net.Socket.connect(Socket.java:589)// at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:542)// at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:414)// at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)// at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:326)// at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:610)// at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:445)// at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835)// at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)// at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)// at A_Test_Thread_Interrupt$HttpRequestRunnable.run(A_Test_Thread_Interrupt.java:35)// at java.lang.Thread.run(Thread.java:748) public static void main(String[] args) { System.out.println("main Start"); long startTime = System.currentTimeMillis(); SharedData sd = new SharedData(); System.out.println("Starting HTTPS Request Thread"); HttpRequestRunnable httpRequestRunnable = new HttpRequestRunnable(sd); Thread workerThread = new Thread(httpRequestRunnable); workerThread.start();// workerThread.stop(); System.out.println("Starting Timeout Thread"); TimeoutRunnable timeoutRunnable = new TimeoutRunnable(workerThread, httpRequestRunnable, sd); Thread timeoutThread = new Thread(timeoutRunnable); timeoutThread.start(); for(int i=0; i<30; i++) { System.out.println("workerThread.getState():"+workerThread.getState()+" timeoutThread.getState():"+timeoutThread.getState()); try { // Sleep for 1 second Thread.sleep(1*1000); } catch (Exception ex) { ex.printStackTrace(); } } long endTime = System.currentTimeMillis(); System.out.println("main End timeInSeconds:"+(endTime-startTime)/1000); } public static class HttpRequestRunnable implements Runnable { SharedData sharedData; public HttpRequestRunnable (SharedData sharedData) { this.sharedData = sharedData; sharedData.setIsFinished(this, false); } public void run() { System.out.println("Running HttpRequestRunnable Runner Start"); long startTime = System.currentTimeMillis(); try { HttpGet httpGet = new HttpGet(URL_THAT_CAUSES_CONNECTION_TIMED_OUT_AFTER_20_SECONDS); sharedData.setHttpGet(this, httpGet); // MOD CloseableHttpResponse response = new DefaultHttpClient().execute(httpGet); String responseString = EntityUtils.toString(response.getEntity()); System.out.println("responseString:"+responseString); sharedData.setIsFinished(this, true); } catch (Exception ex) { ex.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println("Running HttpRequestRunnable Runner End timeInSeconds:"+(endTime-startTime)/1000); } } public static class SharedData { Map<Runnable, Boolean> isFinishedMap = Collections.synchronizedMap(new LinkedHashMap<Runnable, Boolean>()); Map<Runnable, HttpGet> httpGetMap = Collections.synchronizedMap(new LinkedHashMap<Runnable, HttpGet>()); // MOD public void setIsFinished(Runnable runnable, Boolean value) { synchronized(isFinishedMap) { isFinishedMap.put(runnable, value); } } public Boolean getIsFinished(Runnable runnable) { synchronized(isFinishedMap) { return isFinishedMap.get(runnable); } } public void setHttpGet(Runnable runnable, HttpGet httpGet) { // MOD synchronized(httpGetMap) { // MOD httpGetMap.put(runnable, httpGet); // MOD } // MOD } // MOD public HttpGet getHttpGet(Runnable runnable) { // MOD synchronized(httpGetMap) { // MOD return httpGetMap.get(runnable); // MOD } // MOD } // MOD } public static class TimeoutRunnable implements Runnable { Thread workerThreadToKillIfItTakesTooLong; Runnable runnable; SharedData sharedData; public TimeoutRunnable(Thread workerThreadToKillIfItTakesTooLong, Runnable runnable, SharedData sharedData) { this.workerThreadToKillIfItTakesTooLong = workerThreadToKillIfItTakesTooLong; this.runnable = runnable; this.sharedData = sharedData; } public void run() { System.out.println("Running TimeoutRunnable Runnable Start"); long startTime = System.currentTimeMillis(); int secondsToSleep = 1; int iterationsPerNote = 2; int iterations = 10; for(int i=0; i<iterations; i++) { // Sleep for at most 10 seconds boolean workerRunnableIsFinished = sharedData.getIsFinished(runnable); if(workerRunnableIsFinished) { return; } else { if(i % iterationsPerNote == 0) { // Print a message every 2 iterations System.out.println("TimeoutRunnable waiting for workerRunnable..."); } } try { // Sleep for 1 second Thread.sleep(secondsToSleep*1000); } catch (Exception ex) { ex.printStackTrace(); } } // 5 minutes have passed, kill thread System.out.println("Killing worker thread for taking too long"); workerThreadToKillIfItTakesTooLong.stop(); HttpGet httpGet = sharedData.getHttpGet(runnable); // MOD httpGet.abort(); // MOD sharedData.setIsFinished(runnable, true); long endTime = System.currentTimeMillis(); System.out.println("Running TimeoutRunnable Runnable End timeInSeconds:"+(endTime-startTime)/1000); } }}
Here was the modified output
main: main Startmain: Starting HTTPS Request Threadmain: Starting Timeout Thread1st_: Running HttpRequestRunnable Runner Startmain: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: Running TimeoutRunnable Runnable Start2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLEmain: workerThread.getState():RUNNABLE timeoutThread.getState():TIMED_WAITINGmain: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLEmain: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: TimeoutRunnable waiting for workerRunnable...main: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLEmain: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: Killing worker thread for taking too longmain: workerThread.getState():RUNNABLE timeoutThread.getState():RUNNABLE2nd_: Running TimeoutRunnable Runnable End timeInSeconds:10main: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: workerThread.getState():TERMINATED timeoutThread.getState():TERMINATEDmain: main End timeInSeconds:30