multiple execution for real-time message processing - java

I've implemented a thread pool executor on messages that are coming in real-time.
Here is some relevant example code:
class MessageProcessor implements SomeListener{
StateInfo stateInfo;
ExecutorService pool;
MessageProcessor(StateInfo stateInfo) {
pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
this.stateInfo = stateInfo;
}
#Override
void processMessage(final String messageComesInRealTime) {
Runnable runner = new Runnable() {
public void run() {
if(!stateInfo.in_state) {
if(stateInfo.state == 1) {
stateInfo.in_state = true;
//do something with message
stateInfo.state = 2;
}
else if(stateInfo.state == 2) {
stateInfo.in_state = true;
//do something with message
stateInfo.state = 3;
}
//etc...
}
}
};
pool.execute(runner);
//etc...
}
}
In processMessage method, messages come in real-time at a high rate and multiple messages are handled at the same time. But when stateInfo.state becomes true, I don't want other message processes to be evaluated the same way. Is it just better to remove thread altogether for this scenario? Or can there be a way around this behavior while maintaining thread execution? Thanks for any response.

Based on your comments, it sounds like you need to synchronize access and assignment to your in_state variable.
You can do this simply like so:
private final Object lock = new Object();
//...
public void run(){
boolean inState = false;
synchronized(lock){
inState = inState();
if(inState){ setInState(false);}
}
}
boolean inState(){
return this.stateInfo.in_state;
}
void setInState(boolean value){
this.stateInfo.in_state=value;
}
Also be sure to declare the in_state variable in StateInfo to be volatile.

Related

Appropriate way to batch method invocations?

Suppose something like the following:
public boolean doThisThing(SomeArg arg) {
if(iAmAllowedToDoIt()) {
doThing(arg);
return true;
} else {
return false;
}
Suppose that iAmAllowedToDoIt() is a very expensive method, and doThisThing() is invoked by many threads concurrently, and I am allowed to do everything given that I am allowed to do anything, is there a way to batch invocations of iAmAllowedToDoIt() such that I would accumulate SomeArgs in a concurrent data structure, and invoke doThing on all of them at once after resolving iAmAllowedToDoIt only one time without modifying the API? What would that code look like? I can't figure out how to do multithreaded batching performantly like this without modifying the API. An ideal answer would include something that doesn't rely on blocking for a fixed period of time to accumulate invocations of doThisThing().
Ideally it would end up as something like:
Call doThisThing
Call iAmAllowedToDoIt asynchronously
All calls to doThisThing before (2) retuns block until (2) returns
(2) Returns, if true invoke doThing for all blocked doThisThing()s
Your containing object could have an AtomicReference that holds a CompleteableFuture for the computation of iAmAllowedToDoIt(). Additional invocations of doThisThing() simply await the completion of the completable future if one is present or create a new one otherwise, with an appropriate CAS loop to avoid creating more than one instance at a time.
Upon completion the reference is set to null again so that threads invoking the method at a later point can start a new computation.
You could do the following (which implements an algorithm similar to the one proposed by #the8472) :
public class Test {
/**
* Lock used to guard accesses to allowedFuture
*/
private final Object lock = new Object();
/**
* The future result being computed, reset to null as soon as the result is known
*/
private FutureTask<Boolean> allowedFuture = null;
private static final Random RANDOM = new Random();
public boolean doThisThing() throws ExecutionException, InterruptedException {
if (iAmAllowedToDoIt()) {
System.out.println("doing it...");
return true;
}
else {
System.out.println("not doing it...");
return false;
}
}
private boolean iAmAllowedToDoIt() throws ExecutionException, InterruptedException {
// if true, this means that this thread is the one which must really compute if I am allowed
boolean mustCompute = false;
// The Future holding the result which is either the cached one, or a new one stored in the cache
FutureTask<Boolean> result;
synchronized (lock) {
// if no one has computed the result yet, or if it has been computed and thus must be recomputed
// then create it
if (this.allowedFuture == null) {
mustCompute = true;
this.allowedFuture = new FutureTask<>(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
System.out.println("computing if I am allowed...");
Thread.sleep(RANDOM.nextInt(3000));
boolean allowed = RANDOM.nextBoolean();
System.out.println(allowed ? "allowed!" : "not allowed!");
return allowed;
}
});
}
result = this.allowedFuture;
}
if (mustCompute) {
allowedFuture.run();
// reset the cache to null, so that the next thread recomputes the result
synchronized (lock) {
this.allowedFuture = null;
}
}
return result.get();
}
public static void main(String[] args) {
Test test = new Test();
Runnable r = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(RANDOM.nextInt(6000));
test.doThisThing();
}
catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
};
for (int i = 0; i < 50; i++) {
Thread t = new Thread(r);
t.start();
}
}
}

How to use Semaphores for Signaling?

Now I investigate semaphores. I googled following link about this theme:
link
Author of this link wrote about using semaphores for signaling. To show how it works he wrote custom semaphore.
custom semaphore code:
public class Semaphore {
private boolean signal = false;
public synchronized void take() {
this.signal = true;
this.notify();
}
public synchronized void release() throws InterruptedException{
while(!this.signal) wait();
this.signal = false;
}
}
about how use it in code he wrote following:
public class SendingThread {
Semaphore semaphore = null;
public SendingThread(Semaphore semaphore){
this.semaphore = semaphore;
}
public void run(){
while(true){
//do something, then signal
this.semaphore.take();
}
}
}
public class RecevingThread {
Semaphore semaphore = null;
public ReceivingThread(Semaphore semaphore){
this.semaphore = semaphore;
}
public void run(){
while(true){
this.semaphore.release();
//receive signal, then do something...
}
}
}
main:
Semaphore semaphore = new Semaphore();
SendingThread sender = new SendingThread(semaphore);
ReceivingThread receiver = new ReceivingThread(semaphore);
receiver.start();
sender.start();
As I understood order of execution should be following
send - receive
send - receive
send - receive
...
I tryed to write own code using this bluerprint
public class SendReceiveWithCustomSemaphore {
public static void main(String[] args) {
MySemaphore mySemaphore = new MySemaphore();
new Send(mySemaphore).start();
new Receive(mySemaphore).start();
}
}
class MySemaphore {
boolean flag = false;
public synchronized void take() throws InterruptedException {
flag = true;
notify();
}
public synchronized void release() throws InterruptedException {
while (!flag) {
wait();
}
flag = false;
}
}
class Send extends Thread {
MySemaphore mySemaphore;
public Send(MySemaphore semaphore) {
this.mySemaphore = semaphore;
}
#Override
public void run() {
int i = 0;
while (i++ < 10) {
System.out.println("send");
try {
mySemaphore.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Receive extends Thread {
MySemaphore mySemaphore;
public Receive(MySemaphore semaphore) {
this.mySemaphore = semaphore;
}
#Override
public void run() {
while (true) {
try {
mySemaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("receive");
}
}
}
output:
send
send
send
send
send
send
send
send
send
send
receive
Thus it is not expected behaviour for me.
I made a mistake then I wrote code or I didn't understand concept ?
What did author want to say?
Find a better tutorial.
The output that you see is about what I would expect. The "sender" thread never blocks, so it will go on printing "send", "send", "send" forever. Meanwhile, over in the "receiver" thread, each time it calls the semaphore.release() method, it will be blocked until the next time the sender gets to run.
I would expect to see lots of "send" messsages, with occasional "receive" messages mixed in---more or less what you describe seeing.
I don't know what that example is supposed to prove, but for me, it creates the impression that the author does not know how programmers expect Semaphores to behave.
Some authors provide examples of what not to do, or examples containing a deliberate mistake that will be "fixed" in a later example. Are you sure you are not following an example of that kind?
Edit: I followed the link, and it looks like the main problem is that the names were swapped in the definitions of the take() and release() methods. If you just switch the names, it makes more sense.
By the time ReceiveSemafore is started SendSemafore has already executed 10 times.
Consider using a CountDownLatch to start the two threads at the same time. Although as pointed out by Fuhrmanator this will not produce the alternating output that you are looking for.
For this i would use a bounded semaphore with one signal.

Request Queue implementation

I am currently involved in doing POC for an RPC layer. I have written the following method to throttle requests on the client side. Is this a good pattern to follow? I did not choose queueing the additional requests into a threadpool because I am interested only in synchronous invocations and I want the caller thread to block until it is woken up for executing the RPC request and also because threadpool seems additional overhead because of creation of additional threads.
I thought I can manage with the threads which are already issuing the requests. This works well, but the CPU usage is a bit unfair to other processes because as soon as a call ends, another call goes out. I load tested it with a huge number of requests and memory and CPU usage are stable. Can I somehow use ArrayBlockingQueue with poll to achieve the same? Is poll() too much of a CPU hog?
Note: I recognise a few concurrency issues with requestEnd method where it might not wake up all registered items correctly and I am thinking of a performant way to maintain atomicity there.
public class RequestQueue {
// TODO The capacity should come from the consumer which in turn comes from
// config
private static final int _OUTBOUND_REQUEST_QUEUE_MAXSIZE = 40000;
private static final int _CURRENT_REQUEST_QUEUE_INCREMENT = 1;
private static final int _CURRENT_REQUEST_POOL_MAXSIZE = 40;
private AtomicInteger currentRequestsCount = new AtomicInteger(0);
private ConcurrentLinkedQueue<RequestWaitItem> outboundRequestQueue = null;
public RequestQueue() {
outboundRequestQueue = new ConcurrentLinkedQueue<RequestWaitItem>();
}
public void registerForFuture(RequestWaitItem waitObject) throws Exception {
if (outboundRequestQueue.size() < _OUTBOUND_REQUEST_QUEUE_MAXSIZE) {
outboundRequestQueue.add(waitObject);
} else {
throw new Exception("Queue is full" + outboundRequestQueue.size());
}
}
public void requestStart() {
currentRequestsCount.addAndGet(_CURRENT_REQUEST_QUEUE_INCREMENT);
}
//Verify correctness
public RequestWaitItem requestEnd() {
int currentRequests = currentRequestsCount.decrementAndGet();
if (this.outboundRequestQueue.size() > 0 && currentRequests < _CURRENT_REQUEST_POOL_MAXSIZE) {
try {
RequestWaitItem waitObject = (RequestWaitItem)this.outboundRequestQueue.remove();
waitObject.setRequestReady(true);
synchronized (waitObject) {
waitObject.notify();
}
return waitObject;
} catch (NoSuchElementException ex) {
//Queue is empty so this is not an exception condition
}
}
return null;
}
public boolean isFull() {
return currentRequestsCount.get() > _CURRENT_REQUEST_POOL_MAXSIZE;
}
}
public class RequestWaitItem {
private boolean requestReady;
private RpcDispatcher dispatcher;
public RequestWaitItem() {
this.requestReady = false;
}
public RequestWaitItem(RpcDispatcher dispatcher) {
this();
this.dispatcher = dispatcher;
}
public boolean isRequestReady() {
return requestReady;
}
public void setRequestReady(boolean requestReady) {
this.requestReady = requestReady;
}
public RpcDispatcher getDispatcher() {
return dispatcher;
}
}
if (requestQueue.isFull()) {
try {
RequestWaitItem waitObject = new RequestWaitItem(dispatcher);
requestQueue.registerForFuture(waitObject);
//Sync
// Config and centralize this timeout
synchronized (waitObject) {
waitObject.wait(_REQUEST_QUEUE_TIMEOUT);
}
if (waitObject.isRequestReady() == false) {
throw new Exception("Request Issuing timedout");
}
requestQueue.requestStart();
try {
return waitObject.getDispatcher().dispatchRpcRequest();
}finally {
requestQueue.requestEnd();
}
} catch (Exception ex) {
// TODO define exception type
throw ex;
}
} else {
requestQueue.requestStart();
try {
return dispatcher.dispatchRpcRequest();
}finally {
requestQueue.requestEnd();
}
}
If I understood correctly, you want to throttle requests to remote service, by having at most 40 (say) concurrent requests. You can do this easily, without extra threads or services, with a semaphore.
Semaphore s = new Semaphore(40);
...
s.acquire();
try {
dispatcher.dispatchRpcRequest(); // Or whatever your remote call looks like
} finally {
s.release();
}
Use ExecutorService service = Executors.newFixedThreadPool(10); for this.
This will create at the max 10 threads and further requests will wait in the queue. I guess this should help.
Fixed Thread Pool

Creating multithreading java class to process data

I would like to realize class in Java, which will be wait for new data from different threads and when he got it, this class will process it and again go to wait new data. I want to realize this using only synchronized, wait, notifyAll commands. I tried some variants:
1) using one thread, which wait by command lockObject.wait(). But when all active threads finish their work, this thread will be waiting forever. Of course, I can make method stopProcess(), but it is not safety, because another programmer can forget to call it.
2) using one daemon-thread, it will not work, because when all active threads finish their work, my daemon-thread die, but he can have some data which he must to process
3)when new data is coming - create new thread, which will process data. while thread is alive(he process given data), he will receive new data. when it is no data coming and all old data was processed, thread finish to work. Minus of this variant is - when data is coming through some period (when thread have time to process old data and die), a new thread will be created. I think it's bad for performance or/and memory. Am I right?
Is it possible to solve my problem using only one or two(may be using daemon and active thread in combination) threads and not using stopProcess() method??
Here some code
My realize of blocking queue
public class BlockingQueue<T> {
private Queue<T> queue = new LinkedList<T>();
public void add(T el){
synchronized (queue){
queue.add(el);
}
}
public T getFirst(){
synchronized (queue){
return queue.poll();
}
}
public int getSize(){
synchronized (queue){
return queue.size();
}
}
}
Data class
public class Data {
//some data
public void process(){
//process this data
}
}
First variant of code
public class ProcessData {
private BlockingQueue<Data> queue = new BlockingQueue<Data>();
private boolean run = false;
private Thread processThread;
private Object lock = new Object();
public synchronized void addData(Data data) throws Exception {
if (run){
if (data != null){
queue.add(data);
wakeUpToProcess();
}
}else{
throw new Exception("");
}
}
public synchronized void start() {
if (!run){
run = true;
processThread = new Thread(new Runnable() {
public void run() {
while (run || queue.getSize()!=0){
while(queue.getSize() == 0 && run){
//if stopProcess was not called
//and no active threads
//it will not die
waitForNewData();
}
Data cur;
while(queue.getSize() > 0){
cur = queue.getFirst();
cur.process();
}
}
}
});
processThread.start();
}
}
public synchronized void stopProcess() {
if (run){
run = false;
wakeUpToProcess();
}
}
private void waitForNewData(){
try{
synchronized (lock){
lock.wait();
}
}catch (InterruptedException ex){
ex.printStackTrace();
}
}
private void wakeUpToProcess(){
synchronized (lock){
lock.notifyAll();
}
}
}
In second variant I make processThread as daemon. But when active threads die, processThread finish to work, but there are some data in queue, which i have to process.
Third variant
public class ProcessData {
private BlockingQueue<Data> queue = new BlockingQueue<Data>();
private boolean run = false;
private Thread processThread = null;
public synchronized void addData(Data data) throws Exception {
if (run){
if (data != null){
queue.add(data);
wakeExecutor();
}
}else{
throw new Exception("ProcessData is stopped!");
}
}
public synchronized void start() {
if (!run){
run = true;
}
}
public synchronized void stopProcess() {
if (run){
run = false;
}
}
public boolean isRunning(){
return this.run;
}
protected void wakeExecutor(){
if (processThread ==null || !processThread.isAlive()){
processThread = new Thread(new Runnable() {
#Override
public void run() {
Data cur;
while(queue.getSize() > 0){
cur = queue.getFirst();
cur.process();
}
}
});
processThread.start();
}
}
}
It is important, that data must to process in the order, in which it come from threads.
You are seriously reinventing the wheel here. All you want is available in the JDK in the java.util.concurrent package.
Implement a producer-consumer pattern via a BlockingQueue, with your producers calling offer() and your consumer thread calling take(), which blocks until something's available.
That's it. You don't need, and you shouldn't be writing, all those classes you have written. These concurrent classes do all the locking and synchronization for you, and do it correctly too (which is not to be underestimated)
If you're not allowed to use anything from java.util.concurrent then you'll have to implement your own task queue based on something like a LinkedList. I would encapsulate the blocking behaviour in the queue, e.g. (pseudocode)
synchronized Data nextTask() {
while(the linked list is empty) {
wait()
}
remove and return head of the queue
}
synchronized void addTask(Data d) {
add d to the queue
notifyAll()
}
Then you can just have a consumer thread that continuously does something like this
while(true) {
taskQueue.nextTask().process()
}
and the producer threads call taskQueue.addTask to add each task to the queue. If you need a graceful shutdown at the end then you'll either need some "sentinel value" to tell the consumer thread to finish, or find some way of calling Thread.interrupt() at the right time.

producer - consume; how does the consumer stop?

So I have simulated my producer consumer problem and I have the code below. My question is this: how does the consumer stops if he's in constant while(true).
In the code below, I've added
if (queue.peek()==null)
Thread.currentThread().interrupt();
which works nicely in this example. But in my real world design, this doesn't work (sometimes it takes longer time to the producer to 'put' the data so the exception thrown in the consumer is incorrect. In general, I know I can put a 'poison' data such as Object is XYZ and I can check it in the consumer. But this poison makes the code really look bad. Wonder if anyone has a different approach.
public class ConsumerThread implements Runnable
{
private BlockingQueue<Integer> queue;
private String name;
private boolean isFirstTimeConsuming = true;
public ConsumerThread(String name, BlockingQueue<Integer> queue)
{
this.queue=queue;
this.name=name;
}
#Override
public void run()
{
try
{
while (true)
{
if (isFirstTimeConsuming)
{
System.out.println(name+" is initilizing...");
Thread.sleep(4000);
isFirstTimeConsuming=false;
}
try{
if (queue.peek()==null)
Thread.currentThread().interrupt();
Integer data = queue.take();
System.out.println(name+" consumed ------->"+data);
Thread.sleep(70);
}catch(InterruptedException ie)
{
System.out.println("InterruptedException!!!!");
break;
}
}
System.out.println("Comsumer " + this.name + " finished its job; terminating.");
}catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
A: There is simply no guarantee that just because peek returns null, the producer has stopped producing. What if the producer simply got slowed down? Now, the consumer quits, and the producer keeps producing. So the 'peek' -> 'break' idea basically fails.
B: Setting a 'done/run' flag from consumer and reading it in producer also fails, if:
consumer checks the flag, finds it should keep running, then does a 'take'
in meanwhile, producer was setting the flag to 'dont run'
Now consumer blocks forever waiting for a ghost packet
The opposite can also happen, and one packet gets left out un-consumed.
Then to get around this, you will want to do additional synchronization with mutexes over and above the 'BlockingQueue'.
C:
I find 'Rosetta Code' to be fine source of deciding what is good practice, in situations like this:
http://rosettacode.org/wiki/Synchronous_concurrency#Java
The producer and consumer must agree upon an object (or an attribute in the object) that represents end of input. Then the producer sets that attribute in the last packet, and the consumer stops consuming it. i.e. what you referred to in your question as 'poison'.
In the Rosetta Code example above, this 'object' is simply an empty String called 'EOF':
final String EOF = new String();
// Producer
while ((line = br.readLine()) != null)
queue.put(line);
br.close();
// signal end of input
queue.put(EOF);
// Consumer
while (true)
{
try
{
String line = queue.take();
// Reference equality
if (line == EOF)
break;
System.out.println(line);
linesWrote++;
}
catch (InterruptedException ie)
{
}
}
Do NOT use interrupt on Thread, but rather break the loop when not needed anymore :
if (queue.peek()==null)
break;
Or you can also using a variable to mark closing operation pending and then break the loop and close the loop after :
if (queue.peek()==null)
closing = true;
//Do further operations ...
if(closing)
break;
In the real world, most messaging comes with a header of some sort that defines a message type / sub-type or perhaps different objects.
You can create a command and control object or message type that tells the thread to do something when it gets the message (like shutdown, reload a table, add a new listener, etc.).
This way, you can have say a command and control thread just send messages into the normal message flow. You can have the CNC thread talking to an operational terminal in a large scale system, etc.
If your queue can empty before you'd like your consumer to terminate then you'll need a flag to tell the thread when to stop. Add a setter method so the producer can tell the consumer to shutdown. Then modify your code so that instead of:
if (queue.isEmpty())
break;
have your code check
if (!run)
{
break;
}
else if (queue.isEmpty())
{
Thread.sleep(200);
continue;
}
You can use this typesafe pattern with poison pills:
public sealed interface BaseMessage {
final class ValidMessage<T> implements BaseMessage {
#Nonnull
private final T value;
public ValidMessage(#Nonnull T value) {
this.value = value;
}
#Nonnull
public T getValue() {
return value;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ValidMessage<?> that = (ValidMessage<?>) o;
return value.equals(that.value);
}
#Override
public int hashCode() {
return Objects.hash(value);
}
#Override
public String toString() {
return "ValidMessage{value=%s}".formatted(value);
}
}
final class PoisonedMessage implements BaseMessage {
public static final PoisonedMessage INSTANCE = new PoisonedMessage();
private PoisonedMessage() {
}
#Override
public String toString() {
return "PoisonedMessage{}";
}
}
}
public class Producer implements Callable<Void> {
#Nonnull
private final BlockingQueue<BaseMessage> messages;
Producer(#Nonnull BlockingQueue<BaseMessage> messages) {
this.messages = messages;
}
#Override
public Void call() throws Exception {
messages.put(new BaseMessage.ValidMessage<>(1));
messages.put(new BaseMessage.ValidMessage<>(2));
messages.put(new BaseMessage.ValidMessage<>(3));
messages.put(BaseMessage.PoisonedMessage.INSTANCE);
return null;
}
}
public class Consumer implements Callable<Void> {
#Nonnull
private final BlockingQueue<BaseMessage> messages;
private final int maxPoisons;
public Consumer(#Nonnull BlockingQueue<BaseMessage> messages, int maxPoisons) {
this.messages = messages;
this.maxPoisons = maxPoisons;
}
#Override
public Void call() throws Exception {
int poisonsReceived = 0;
while (poisonsReceived < maxPoisons && !Thread.currentThread().isInterrupted()) {
BaseMessage message = messages.take();
if (message instanceof BaseMessage.ValidMessage<?> vm) {
Integer value = (Integer) vm.getValue();
System.out.println(value);
} else if (message instanceof BaseMessage.PoisonedMessage) {
++poisonsReceived;
} else {
throw new IllegalArgumentException("Invalid BaseMessage type: " + message);
}
}
return null;
}
}

Categories

Resources