Threads and Interrupts: Continue or exit? - java

The official documentation and forum posts I could find are very vague on this. They say it's up to the programmer to decide whether to continue after being interrupted or exit, but I can't find any documentation of the conditions that would warrant one or the other.
Here is the code in question:
private final LinkedBlockingQueue<Message> messageQueue = new LinkedBlockingQueue<Message>();
// The sender argument is an enum describing who sent the message: the user, the app, or the person on the other end.
public void sendMessage(String address, String message, Sender sender) {
messageQueue.offer(Message.create(address, message, sender));
startSenderThread();
}
private Thread senderThread;
private void startSenderThread(){
if(senderThread == null || !senderThread.isAlive()){
senderThread = new Thread(){
#Override
public void run() {
loopSendMessage();
}
};
senderThread.start();
}
}
private void loopSendMessage(){
Message queuedMessage;
// Should this condition simply be `true` instead?
while(!Thread.interrupted()){
try {
queuedMessage = messageQueue.poll(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
EasyLog.e(this, "SenderThread interrupted while polling.", e);
continue;
}
if(queuedMessage != null)
sendOrQueueMessage(queuedMessage);
else
break;
}
}
// Queue in this context means storing the message in the database
// so it can be sent later.
private void sendOrQueueMessage(Message message){
//Irrelevant code omitted.
}
The sendMessage() method can be called from any thread and at any time. It posts a new message to send to the message queue and starts the sender thread if it isn't running. The sender thread polls the queue with a timeout, and processes the messages. If there are no more messages in the queue, the thread exits.
It's for an Android app that automates SMS message handling. This is in a class that handles the outbound messages, deciding whether to immediately send them or save them to send later, as Android has an internal 100 message/hour limit that can only be changed by rooting and accessing the settings database.
Messages can be sent from different parts of the app simultaneously, by the user or the app itself. Deciding when to queue for later needs to be handled synchronously to avoid needing atomic message counting.
I want to handle interrupts gracefully, but I don't want to stop sending messages if there are more to send. The Java documentation on threading says most methods simply return after being interrupted, but that will leave unsent messages in the queue.
Could anyone please recommend a course of action?

I guess the answer depends on why you are being interrupted? Often threads are interrupted because some other process/thread is trying to cancel or kill it. In those cases, stopping is appropriate.
Perhaps when interrupted, you send out all remaining messages and don't accept new ones?

Related

How to keep the calling function thread on hold till the time all the threads processing gets completed?

I am working on a scenario as described below:
We are consuming messages from kafka, and each message received should be processed in parallel, given that I have to keep on hold the main( or calling) thread until all the messages received(1 message-1 thread) are done with processing.
Given that number of messages is known and is available from the kafka message headers.
Once the processing is completed for all the threads, only after that the calling thread should proceed ahead.
I tried using CountDownLatch with the count as number of messages going to be received, but using this, it is keeping the main thread on hold, and not allowing to consume the next messages.
Is there anyway, by which this can be achieved ?
Code Snippet:
class MessageHandler{
#Autowired private ProcessorAsync processorAsync;
public void handle()
{
CountdownLatch countdown = new CountdownLatch(noOfMessages);
CompletableFuture<Void> future = processorAsync.processMessage(message,countdown);
countdown.await();
if(future.isDone())
{//post msg processing methods/api calls
m1();
m2();
}
}
}
class ProcessorAsync
{
#Async("customThreadPool") // max 20 threads
public CompletableFuture<Void> processMessage(Message msg, CountdownLatch countdown)
{
//DB update statements
// .
countdown.countdown();
return CompletableFuture.allOf();
}
}

How can I attempt to restart() JMS connection in concurrent environment?

I have a JMS application which tries to read from a JBosss Queue. I implemented MessageListener on my class and used the onMessage() to receive messages
public class JBossConnector implements MessageListener, AutoCloseable {}
Here is my method:
/**
* The listener method of JMS. It listens to messages from queue: 'jbossToAppia'
* If the message is of type MessageObject, then transfer that to Appia
*
* #param message JMS Message
*/
#Override
public void onMessage(Message message) {
// receive the message from jboss queue: 'jbossToAppia'
// then post it to appia
if (message instanceof ObjectMessage) {
try {
MessageObject messageObject = (MessageObject) ((ObjectMessage) message).getObject();
System.out.printf("JbossConnector: MessageObject received from JBOSS, %s\n", messageObject.getMessageType());
component.onMessageFromJboss(properties.getProperty("target.sessionID"), messageObject);
} catch (MessageFormatException exception) {
logger.error(ExceptionHandler.getFormattedException(exception));
ExceptionHandler.printException(exception);
} catch (JMSException exception) {
ExceptionHandler.printException(exception);
restart();
}
} else {
System.out.printf("%s: MessageFormatException(Message is not of the format MessageObject)\n", this.getClass().getSimpleName());
}
}
Whenever I find a JMSException I try to restart JBoss connection (Context, Connection, Session, Receiver, Sender). What my doubt is that I've read onMessage() uses multiple threads to receive messages from queue (correct me if I'm wrong).
When the JBoss queue connection severs, there would be at least some queues that throw this exception. That means they all will try to restart() the connection which is a waste of time (restart() first closes all the connections, sets the variables to null and then attempt to initiate connections).
Now I could do something like
synchronized (this){
restart();
}
or use volatile variables. But that would not guarantee that other threads won't attempt to restart() when current threads finishes the restart() operation (again correct me if I'm wrong).
Is there any solution to make this work?
The onMessage() of a MessageListener is indeed run from its own thread so you'll need proper concurrency controls. I think the simplest solution would just be to use a java.util.concurrent.atomic.AtomicBoolean. For example, in your restart() method you could do something like this:
private void restart() {
AtomicBoolean restarting = new AtomicBoolean(false);
if (!restarting.getAndSet(true)) {
// restart connection, session, etc.
}
}
This will make the restart() method effectively idempotent. Multiple threads will be able to call restart() but only the first thread which calls it will actually cause the resources to get re-created. All other calls will return immediately.

Returning a value from thread

First of all, yes I looked up this question on google and I did not find any answer to it. There are only answers, where the thread is FINISHED and than the value is returned. What I want, is to return an "infinite" amount of values.
Just to make it more clear for you: My thread is reading messages from a socket and never really finishes. So whenever a new message comes in, I want another class to get this message. How would I do that?
public void run(){
while(ircMessage != null){
ircMessage = in.readLine();
System.out.println(ircMessage);
if (ircMessage.contains("PRIVMSG")){
String[] ViewerNameRawRaw;
ViewerNameRawRaw = ircMessage.split("#");
String ViewerNameRaw = ViewerNameRawRaw[2];
String[] ViewerNameR = ViewerNameRaw.split(".tmi.twitch.tv");
viewerName = ViewerNameR[0];
String[] ViewerMessageRawRawRaw = ircMessage.split("PRIVMSG");
String ViewerMessageRawRaw = ViewerMessageRawRawRaw[1];
String ViewerMessageRaw[] = ViewerMessageRawRaw.split(":", 2);
viewerMessage = ViewerMessageRaw[1];
}
}
}
What you are describing is a typical scenario of asynchronous communication. Usually solution could be implemented with Queue. Your Thread is a producer. Each time your thread reads a message from socket it builds its result and sends it into a queue. Any Entity that is interested to receive the result should be listening to the Queue (i.e. be a consumer). Read more about queues as you can send your message so that only one consumer will get it or (publishing) means that all registered consumers may get it. Queue implementation could be a comercialy available products such as Rabbit MQ for example or as simple as Java provided classes that can work as in memory queues. (See Queue interface and its various implementations). Another way to go about it is communication over web (HTTP). Your thread reads a message from a socket, builds a result and sends it over http using let's say a REST protocol to a consumer that exposes a rest API that your thread can call to.
Why not have a status variable in your thread class? You can then update this during execution and before exiting. Once the thread has completed, you can still query the status.
public static void main(String[] args) throws InterruptedException {
threading th = new threading();
System.out.println("before run Status:" + th.getStatus());
th.start();
Thread.sleep(500);
System.out.println("running Status:" + th.getStatus());
while(th.isAlive()) {}
System.out.println("after run Status:" + th.getStatus());
}
Extend thread to be:
public class threading extends Thread {
private int status = -1; //not started
private void setStatus(int status){
this.status = status;
}
public void run(){
setStatus(1);//running
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
setStatus(0); //exit clean
}
public int getStatus(){
return this.status;
}
}
And get an output of:
before run Status:-1
running Status:1
after run Status:0

String based thread communication

I need to be able to 'send' a string from one thread to 1 or more other threads. But I have no idea how to do this.
Basically, I have a server who has one connection that sends commands to it. I need to send these commands to all the other threads, so they can send them to their clients.
How can I have a single string that is referenced by all the other threads. How to know when all the threads executed the command string?
Somewhere you will need a List of your Runnabless like:
List<MyRunnable> runningThreads;
Then you will have an implementation of Runnable:
class MyRunnable implements Runnable {
public void run() { ... }
}
Now you need to have some way of sending a message to that Runnable.
class MyRunnable implements Runnable {
public void run() { ... }
public void sendMessage( String message ){ ... }
}
So to send all the runnable a message it's as easy as:
for( MyRunnable runnable : runningThreads ){
sendMessage( "Hello There!" );
}
What to do now depends heavily on what you want to do next with the message. In any way it has to appear somehow in the Thread's visible range. So for starters lets save it in a variable:
class MyRunnable implements Runnable {
private volatile String myLastMessage;
public void run() { ... }
public void sendMessage( String message ){
this.myLastMessage = message;
}
so if you're run is already run periodically you can get off with:
public void run(){
while( true ){
Thread.sleep( 1000 ); //1s
if( lastMessage != null ){
doSomethingWith( lastMessage );
lastMessage = null;
}
}
}
If you need more than one message stored in the Thread you can use e.g. SynchronizedList for this.
If you need your Thread to react instantly on the message it received then use a monitor and
notifyAll method. See e.g. here: http://www.programcreek.com/2009/02/notify-and-wait-example/
If I understand you right, this is your setup:
How can I have a single string that is referenced by all the other threads?
When the string is sent via sockets or similar, it will be a different string. But with the same content, and that's what counts here. So I would not care too much about this point.
How to know when all the threads executed the command string?
Have each thread sent back a confirmation to the server whenever the thread finished processing a command for all clients. The server keeps track of all commands sent and confirmations received.
Keep in mind, that threads may crash, connections may break and the execution of a command may not succeed in a timely fashion, or fail entirely.
Perhaps you are refering to the Observer pattern (aka, Publish–subscribe pattern). The server (publisher) needs to know their clients (subscribers) in order to send a common message, so you need a data structure. There are several ways to implement this. See the next links:
Observer pattern with threads
The concurrent implementation of a publisher/subscriber pattern
Chaining of observer/observable pattern

BlockingQueue consumer has no response while queue is not empty

I have a distributed system, whose node receive message objects through socket. The messages are written to a BlockingQueue when received and processed in another thread. I make sure that there is just one BlockingQueue instance within a machine. The incoming rate for is very high, roughly thousands per second. The consumer works well at first, but blocks (have no response at all) after a certain period - I have checked that BlockingQueue is not empty, so should not be blocked by BlockingQueue.take(). When I manually decrease the rate of incoming message objects, the consumer works absolutely well. This is quite confusing...
Could you help me identify the problem? Thanks a lot in advance.
Consumer code:
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat(id+"-machine-worker")
.setDaemon(false)
.setPriority(Thread.MAX_PRIORITY)
.build();
ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
executor.submit(new Worker(machine));
public static class Worker implements Runnable {
Machine machine;
public Worker(Machine machine) {
this.machine = machine;
}
#Override
public void run() {
while (true) {
try {
Message message = machine.queue.take();
// Do my staff here...
} catch (Exception e) {
logger.error(e);
}
}
}
}
Producer code:
// Below code submits the SocketListener runnable described below
ExecutorService worker;
Runnable runnable = socketHandlerFactory.getSocketHandlingRunnable(socket, queue);
worker.submit(runnable);
public SocketListener(Socket mySocket, Machine machine, LinkedBlockingQueue<Message> queue) {
this.id = machine.id;
this.socket = mySocket;
this.machine = machine;
this.queue = queue;
try {
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream(), 8192*64);
ois = new ObjectInputStream(bis);
} catch (Exception e) {
logger.error("Error in create SocketListener", e);
}
}
#Override
public void run() {
Message message;
try {
boolean socketConnectionIsAlive = true;
while (socketConnectionIsAlive) {
if (ois != null) {
message = (Message) ois.readObject();
queue.put(message);
}
}
} catch (Exception e) {
logger.warn(e);
}
}
If you are using an unbounded queue, it may happen that the whole system is getting bogged down due to memory pressure. Also, this means that the producing intensity is not limited by the consuming intensity. So, use a bounded queue.
Another advice: get a full thread stacktrace dump when your blocking condition occurs to find out for certain where the consumer is blocking. You may get a surprise there.
You have several candidate problem areas:
What actual BlockingQueue are you using? Did you hit the upper limit of an ArrayBlockingQueue?
How much memory did you allocate for your process? I.e., what is the max heap for this process? If you hit the upper limit of that heap space from your overload of incoming messages, it's entirely possible that you had an OutOfMemoryError.
What actually happens during your message processing ("Do my staff here..." [sic])? Is it possible that you have a deadlock inside that code that you only expose when you send many messages per second. Do you have an Exception eater somewhere down in that call stack that's hiding the real problem that you're experiencing?
Where are your loggers logging to? Are you throwing away the indicative message because it's not logging to a location that you expect?

Categories