I have a thread that executes the following code:
public void run() {
try {
int n = 0;
byte[] buffer = new byte[4096];
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
out.flush();
}
} catch (IOException e) {
System.out.println(e);
}
}
where in
is System.in
. How can I stop such thread gracefully? Neither closing System.in
, nor using Thread.interrupt
appear to work.
This is because reading System.in (InputStream) is a blocking operation.
Look here Is it possible to read from a InputStream with a timeout?
You've stumbled upon a 9 year old bug no one is willing to fix. They say there are some workarounds in this bug report . Most probably, you'll need to find some other way to set timeout (busy waiting seems unavoidable).
You could use the available() method (which is non-blocking) to check whether there is anything to read beforehand.
In pseudo-java:
//...
while(running)
{
if(in.available() > 0)
{
n = in.read(buffer);
//do stuff with the buffer
}
else
{
Thread.sleep(500);
}
}
//when running set to false exit gracefully here...
I had the same problem today, and this is how I fixed it, using in.ready()
:
public void run() {
String line;
// Some code
while(!Thread.currentThread().isInterrupted()){
try {
if (in.ready()) {
line = in.readLine();
}
} catch (Exception e) {
try {
Thread.currentThread().wait(500);
} catch (InterruptedException e1) {
// Do what we want when thread is interrupted
}
}
}
}
Is it safe to close in stream in other thread? It works for me. In this case, in.read(...)
throws exception SocketException
.
If you want to give a user some time to enter data - maybe to allow overriding default values or interrupting some automated process -, then wait first and check available input after the pause:
System.out.println("Enter value+ENTER within 5 Seconds to override default value: ");
try{
Thread.sleep(5000);
} catch {InterruptedException e){}
try{
int bytes = System.in.available();
if (bytes > 0) {
System.out.println("Using user entered data ("+size+" bytes)");
} else {
System.out.println("Using default value");
}
} catch(IOException e) { /*handle*/ }
you can use a external flag for this
boolean flag = true;
public void run() {
try {
int n = 0;
byte[] buffer = new byte[4096];
while ((n = in.read(buffer)) != -1 && flag) {
out.write(buffer, 0, n);
out.flush();
}
} catch (IOException e) {
System.out.println(e);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.