How to stop thread without waiting client response - java

I have a "ClientsHandler" class that reads client input and converts it into a server command.
The problem is that when I use the exit command in the server console, runFlag is set to false and the loop starts waiting for the last input from the client before closing the thread. How can I break the loop and stop the thread instantly after exit command?
class ClientsHandler(
private val socket: Socket,
private val commandManager: CommandManager
) : Runnable {
companion object {
var runFlag = true
fun close() {
runFlag = false
}
}
override fun run() {
var input = ObjectInputStream(socket.getInputStream())
var output = ObjectOutputStream(socket.getOutputStream())
var username = (input.readObject() as User).username
println("$username connected")
while (runFlag) {
try {
var request = input.readObject() as ServerRequest
output.writeObject(ServerCommandInvoker.invoke(request, commandManager))
} catch (e: Exception) {
println("$username disconnected")
runFlag = false
}
}
input.close()
output.close()
socket.close()
}
}

Two options.
Interrupt
This is a tricky one, in that the Java library spec explicitly reserves the right for this not to work. On most platforms it does work, but you should probably skip it and go for the second option below.
The idea is, theThreadThatIsCurrentlyBlockingOnTheReadObjectCall.interrupt() will generally cause that readObject() call to exit immediately with an IOException whose message states something along the lines of 'thread interrupted'. You can now continue.
The reason this is not guaranteed is because java needs to run on a very wide array of platforms and hardware and perhaps not all of them can do this.
Just close the socket
Instead, from the thread that is setting the runFlag to false, you can also just close the socket directly. This will, definitely, cause that readObject() call that's still running to exit immediately with an IOException indicating that the socket is now closed.
Note that your setting of the runFlag appears invalid to me, in that it doesn't use volatile or synchronized or some other mechanism to ensure this field update is actually visible from the other thread reliably. the JVM is free to make that runFlag change be visible to your ClientsHandler run method, or not - JVM's choice. So you can't even test that your code is broken.
Generally for purposes like this, you can use an AtomicBoolean, which guarantees that writes in one thread are visible to another without a potentially very long delay.

Related

Java - synchronized lock hangs tablet (Bluetooth LE Android)

I have a Unity3D app with a Java plugin I've written in Android Studio for accessing a BluetoothLE server over on my Raspberry Pi 3 from my Android device, as well as an Objective-C plugin for XCode on the IOS side for CoreBluetooth. On the plugin side my Objective-C code works perfectly on IOS, but my Java crashes and burns on Android, and freezes the whole tablet, I'm not too surprised. Also notably, it's already taken me about 3x longer so far to code plugin support in Java. Maybe it's time to have a fresh set of eyes looking at it.
The difference is that CoreBluetooth's functions on IOS seem to read a GATT characteristic synchronously while Java requires asynchronous callbacks that don't seem to be working for me. It causes Unity and the entire tablet to hang until reboot.
Here is the part causing problems (it's two parts).
This first part is where I have Unity telling BluetoothLE to go start reading the pins (GetPins). I wanted it to basically act synchronously and wait until it's retrieved data so it can return a string like I've coded in the IOS version so I have it do a synchronized lock.
Basically Java is imposing an asynchronous coding model that's unnecessary on the IOS side (in fact, I'm not so sure there's an asynchronous way to code GATT characteristic reading on IOS CoreBluetooth, but I could be wrong), that would cause me to have to rewrite my entire plugin structure from Unity to support what Java's doing, which is going to be a lot more fiddly in the end and may break other things in the process.
public String GetPins() {
String returnValue = "";
if (mConnected) {
try {
if (getPinsCharacteristic == null) {
List<BluetoothGattService> services = mGatt.getServices();
if (mServiceRead == null) {
mGatt.discoverServices();
mServiceWrite = mGatt.getService(ServiceWriteUUID);
mServiceRead = mGatt.getService(ServiceReadUUID);
mServiceNotify = mGatt.getService(ServiceNotifyUUID);
}
getPinsCharacteristic = mServiceRead.getCharacteristic(PinsCharacteristic);
}
} catch(Exception ex) {
Log.i("MERRRRRP",String.format("Exception: (%s)",ex.toString()));
}
Log.i("MERRRRRP", "Reading Pins");
if (getPinsCharacteristic != null) {
try {
boolean success = mGatt.readCharacteristic(getPinsCharacteristic);
isReadingPins = true;
while(isReadingPins) {
synchronized (readLockPins) {
try {
readLockPins.wait(1);
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
}
}
returnValue = new String(getPinsCharacteristic.getValue(), "UTF-8");
}
catch(Exception ex) {
returnValue = ex.toString();
}
}
}
return returnValue;
}
Now this is the part onCharacteristicRead where it's actually getting the result back, and should be unlocking the synchronized lock and I should get the value back. Instead the whole tablet is freezing.
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
if (characteristic.equals(getPinsCharacteristic)) {
synchronized (readLockPins) {
isReadingPins = false;
}
}
}
}
Your first block of code acquiring lock in a loop and holding it for one second. You assume that your second block of code will execute and acquire the lock between those iterations in first block.
That assumption is wrong. The locks are not fair. If thread A is acquiring and releasing a lock in the loop, and thread B is trying to acquire that same lock, there is not guarantee, that thread B gets it in reasonable time (or maybe never).
The second potential problem (I cannot determine from the code you just posted) is that the variable isReadingPins in while(isReadingPins) MUST be volatile.
Variables not marked volatile do not trigger memory barrier operation, which results in the scenario where writing to the variable in one thread is not visible in another thread.
In your case, isReadingPins = false; in second code block will probably not be visible to the thread running the first code block, because value of the variable will in cache local to the CPU core running that code block, which will always be true, because the write to false is local to another CPU core and CPU core caches will not be synchronized due to absence of memory barrier. This is why the variable must be volatile.
In the end, this is pretty clumsy way of doing this. I don't know Android API, but in regular Java this would be solved using a promise/future or at least a simple Latch.
edit And another thing... if your read function fails, or returns something that is not GATT_SUCCESS, then isReadingPins is never set to false and your application just freezes. This is bad design.

How can I stop a Java Thread from another one?

Maybe I'm thinking to complicated, but I have the following situation:
I have a class Server.java extending Thread with the following relevant part of the code:
public void run() {
while(listening) {
try {
ServerThread cst = new ServerThread(serverSocket.accept());
cst.start();
} catch (IOException e) {
listening = false;
System.out.println(e.getMessage());
}
}
}
My ServerThread then handles all the incoming stuff.
My question now is, if there is any possibility to stop this Thread (Server) like for example over the command line.
I tried to add a new class, that would handle command line input and .interrupt() this Thread, but that kinda just made a big mess..
Here's one way:
Provide a setter for listening that can be accessed from another class/thread.
Set a reasonable timeout (say, 1 sec) on the ServerSocket and handle the SocketTimeoutException.
To stop the thread, set listening to false and within 1 second the thread will stop. If you want finer control, investigate the async I/O classes in java.nio.
You can define listening as volatile, with a setter and set that to false from another class whenever you want to stop the Thread.

Checking if a Thread is sleeping always returns true

I currently have the following problem:
I have made a 'Cache Updater Thread', which checks for updates and then sleeps for some amount of time. I have also build a Button, which enables the user to check for updates manually. The Thread is built like this:
public static Thread cacheUpdater = new Thread(new Runnable() {
int milliSecondSleepTime = 10000;
public void run() {
try {
cacheUpdater.setPriority(Thread.MIN_PRIORITY);
//Infinite loop
while (!terminate) {
syncStatus.set(0);
//Check for updates with some methods, not important here.
syncStatus.set(1);
Thread.sleep(this.milliSecondSleepTime);
}
}
catch (InterruptedException e) {
//First check if it is termination time
if (!terminate) {
syncStatus.set(0);
this.run();
}
}
catch (Exception e) {
System.out.println(e);
}
return;
}
});
If the user clicks the manual-update button, the following code is being runned:
#FXML public void syncOnRequest() {
//Only call interrupt, because then it will start again when terminate is still false
CacheManager.cacheUpdater.interrupt();
System.out.println(CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING));
while (!CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING)) {
//LOOP FOREVER
}
//Some code that needs to be executed after the cache is updated
}
I would like to continue executing code in the syncOnRequest() method, when the cache updater is ready with its manual update. I had the idea to check if it is sleeping, but this is not working, because the System.out.println() immediately returns true. I have measured the time it takes to do the update, and its between 200 and 400 ms.
What am I doing wrong here? And why is it always returning true?
Additional question: sometimes a click on the button just kills the Thread, because it just woke up. The InterruptedException is not thrown.
How can I make sure the Thread will also restart in that case?
Note that Thread#interrupt() is the only polite way to ask your thread to interrupt itself (unless you explicitly implement another). Using it to restart the check is therefore a bad practice. So is checking the thread state for synchronization purposes and exposing the thread that keeps your cache up-to-date to external clients.
You manager should have a updateCache() method you will call directly from UI code and auto-update thread will call the same method periodically*. In that method, make sure that access to your cached data is either correctly synchronized or it happens atomically.
*) Instead of implementing your own periodic thread, consider using
Timer and TimerTask classes as well as making it a daemon thread.

how to close a thread which is doing IO operation

I am having a scenario :
I have a thread which is calling a method where i use Default HTTP client to execute a request. for getting the response I open an InputStream and use a Buffred Reader to read the stream.
While(s = buffer.readline .... )
Inside the while loop i keep looking at the response and see for a string " Hello " ...If i get the string i send the response object back ..
The While loop executes till i get the string
The while loop executes till i press the back key ( android )
Now the scenario works for my 1st point. But i face issue in the 2nd point.
When i press back key, i need to stop my thread.
but i am not able to do it. I tried :
thread.destroy
thread.interrupt
thread = null
None of the above works. In fact my thread is always running...
I am not clear if the issue is with Thread or the issue is with the While loop of the stream.
Because i see that the while loop is executing always..
Please help me the best way i can solve this issue...Whether close the thread or close the stream.
Please help me find way to close the stream and close the thread.
thread.destroy() is deprecated. Do not use it.
The safest way to stop an IO bound thread is by interrupting it.
The thread's logic must cooperate by (1) checking for isInterrupted() status and
(2) catching InterruptedException exception.
It is important that both #1 and #2 above will be handled. interrupt()ing a
thread can in some occasions result in exceptions and in others in setting of
status with no exception!
A safe thread implementation goes like this:
class MyThread {
private volatile boolean wasStopped;
public void run() {
try {
while (!Thread.currentThread().isInterrupted() && !wasStopped) {
do_thread_work();
}
} catch (InterruptedException e) {
return; // gracefully stop thread
}
}
public void gracefullyStop() {
wasStopped = true;
this.interrupt();
}
}
To stop the thread call
thread.gracefullyStop();
This pattern will work fine as long as the thread logic function (do_thread_work)
will not internally catch & dismiss InterruptedException. Be aware.
You will see other implementations that rely solely on isInterrupted() check
without the additional wasStopped flag. I think this is a bad practice.
Why?
Because if the interrupt() was raised while the thread was in a waiting mode
i.e. inside functions wait() join() or sleep(), the thread will indeed be woken,
but its interrupted status will be set to false.
Good luck.

What is the correct way to stop a thread waiting for network activity?

This question has no doubt been asked in various forms in the past, but not so much for a specific scenario.
What is the most correct way to stop a Thread that is blocking while waiting to receive a network message over UDP.
For example, say I have the following Thread:
public class ClientDiscoveryEngine extends Thread {
private final int PORT;
public ClientDiscoveryEngine(final int portNumber) {
PORT = portNumber;
}
#Override
public void run() {
try {
socket = new DatagramSocket(RECEIVE_PORT);
while (true) {
final byte[] data = new byte[256];
final DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
}
} catch (SocketException e) {
// do stuff 1
} catch (IOException e) {
// do stuff 2
}
}
}
Now, would the more correct way be using the interrupt() method? For example adding the following method:
#Override
public void interrupt() {
super.interrupt();
// flip some state?
}
My only concern is, is socket.receive() not a non-interruptable blocking method? The one way that I have thought of would be to implement the interrupt method as above, in that method call socket.close() and then cater for it in the run method in the catch for the SocketException. Or maybe instead of while(true) use some state that gets flipped in the interrupt method. Is this the best way? Or is there a more elegant way?
Thanks
The receive method doesn't seem to be interruptible. You could close the socket: the javadoc says:
Any thread currently blocked in receive(java.net.DatagramPacket) upon
this socket will throw a SocketException
You could also use setSoTimeout to make the receive method block only for a small amount of time. After the method has returned, your thread can check if it has been interrupted, and retry to receive again for this small amount of time.
Read this answer Interrupting a thread that waits on a blocking action?
To stop a thread, you should not user neither interrupt nor stop in java. The best way, as you suggested by the end of your question, is to have the loop inside the main method controlled by a flag that you can rise as needed.
Here is an old link about this :
http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
Other ways of stopping a thread are deprecated and don't provide as much control as this one. Also, this may have changed a bit with executor services, I didn't have time to learn much about it yet.
Also, if you want to avoid your thread to be blocked in some IO state, waiting for a socket, you should give your socket a connection and reading time out (method setSoTimeout).
Regards,
Stéphane
This is one of the easier ones. If it's blocked on a UDP socket, send the socket a UDP message that instructs the receiving thread to 'stop'.
Rgds,
Martin

Categories

Resources