I am developing a plugin for a system, the plugin catches some events in that system, wraps them and pushes out to another system for analysis. The overhead generated by the plugin must be as low as possible, because the main system will be blocked until the plugin finishes work. So what I have so far is that I catch the event and push it into a BlockingQueue
and another thread is listening, if the queue gets an item it will try to push it out from the system.
@Override public void start(){ StatsManager statsManager = new StatsManager(); } //catch event public void taskFinished(){ statsManager.pushData(Context.getData()); }
The StatsManager:
private BlockingQueue<MyItem> blockingQueue; public StatsManager(){ blockingQueue = new ArrayBlockingQueue<MyItem>(32768); SenderThread sender = new SenderThread(blockingQueue); new Thread(sender).start(); } public void pushData(ItemFromContext ctxItem){ try { MyItem item = CollectInterestingData(ctxItem); blockingQueue.put(item); } catch (InterruptedException e) { logger.error(e.toString()); // Is the thread interrupted anyway? Thread.currentThread().interrupt(); } } private class SenderThread implements Runnable{ private BlockingQueue<MyItem> blockingQueue; public SenderThread(BlockingQueue<MyItem> queue){ blockingQueue = queue; } @Override public void run() { while (true){ try { MyItem item = blockingQueue.take(); postItem(item); } catch (InterruptedException e) { logger.error(e.toString()); Thread.currentThread().interrupt(); } } }
In the other end, a REST service is waiting. Once it receives an item, it pushes it into a BlockingQueue
and returns. Another thread is listening to that queue and once item arrives, it writes it down to database.
What problem I do not foresee? One thing that seems obvious is that I am not handling situation where other end fails to receive.
I am not very experienced with this kind of stuff. Does it make sense at all? All comments will be warmly welcomed.
EDIT 1
I read from the BlockingQueue
docs:
put(E e) Inserts the specified element at the tail of this queue, waiting for space to become available if the queue is full.
Do I understand correctly that should the queue be full, the thread will simply hang until space becomes available in the queue, hence blocking the whole systems execution? This is, of course, the worst that could happen to me. I am going to use offer
for now, unless somebody suggests anything better.
offer(E e) Inserts the specified element at the tail of this queue if it is possible to do so immediately without exceeding the queue's capacity, returning true upon success and false if this queue is full.
So the balance here would be whether I risk losing some data or I risk blocking the whole system.
Also, would it make sense to implement the whole StatsManager
as Runnable
and use ThreadPoolExecutor
to spin off wrapping and sending tasks? Could that be more efficient? Would this be thread-safe?
If it's relevant, I am expecting roughly 80000-100000 items per 24 hours.