Question about blocking queue
Hi all.
Working on a small web server in java (personal project, it is nothing serious or advanced and done just for fun). In any case I have decided to move the logging into a dedicated thread. Was going to implement it with wait/notify, but I read somewhere that this may be useful for this kind of situation:
BlockingQueue (Java Platform SE 6)
What I want is basically a dedicated thread that sits and wait until something is added to a queue containing stuff to log. It will then pass that on to its listeners, which will then do as they please with that information (like they can write it to the standard output stream or show it in a window or something). Would a blocking queue be good for this?
At the moment I do not have that much code, just wanted to ask first to clear things up. Have a few more questions if a blocking queue is the way to go. And as a note, I would to be honest not have any issue with making a wait/notify approach, but I want to learn something new :).
Take care,
Kerr.
Re: Question about blocking queue
Yes, a blocking queue would be a very good way to go. You can have your log processing thread check to see if there's anything on the queue, and if so, pull it off and process it. Other threads can add items into the queue whenever they want, and you should have basically everything setup quickly. A BlockingQueue also scales very well. Say you decided that one log thread wasn't enough. You could simply add a second log thread, which would pull items off the Queue. Similarly, you can easily add as many other threads which would add items onto that queue.
Re: Question about blocking queue
Thanks :). Have modified my logger to use it. There is one think I am wondering about, though. Should I use an ArrayBlockingQueue or a LinkedBlockingQueue? I am at the moment using the ArrayBlockingQueue. Also, how would I handle an InterruptedException the best way? Since the put and take methods both throw them, that is. At the moment, when something get logged I return if it got logged or not. The idea is that I donīt want the rest of the program to worry about an InterruptedException, and if they want to handle if something doesnīt get logged they can by checking the return value. Donīt know if that is a good approach, though. Here is my code:
Code java:
public class SimpleLogger
{
// Declare the list of listeners
private List<LogListener> mListeners;
private BlockingQueue<Entry> mEntryQueue;
private Thread mLogThread;
/**
* Constructor
*/
public SimpleLogger()
{
mListeners = new ArrayList<LogListener>();
mEntryQueue = new ArrayBlockingQueue<Entry>(25, true);
mLogThread = new Thread(new LoggerThread());
mLogThread.start();
}
/**
* Registers a log listener to be notified when
* something get logged
*
* @param l the new log listener
*/
public synchronized void registerListener(LogListener l)
{
mListeners.add( l );
}
/**
* Logs something without a client ip or path
*
* @param cat the category of the log entry
* @param title the title of the log entry
* @param desc the description of the log entry
*/
public boolean log(Category cat, String title, String desc)
{
return this.log(cat, title, desc, null, null);
}
/**
* Logs something with a client ip, but without a path
*
* @param cat the category of the log entry
* @param title the title of the log entry
* @param desc the description of the log entry
* @param clientIP
*/
public boolean log(Category cat, String title, String desc, String clientIP)
{
return this.log(cat, title, desc, clientIP, null);
}
/**
* Logs something with a client ip and a path
*
* @param cat the category of the log entry
* @param title the title of the log entry
* @param desc the description of the log entry
* @param clientIP the ip address of the client
* @param path the path to connect to the entry
*/
public synchronized boolean log(Category cat, String title, String desc, String clientIP, String path)
{
boolean success = true;
// The reason I am doing it this way is because the logger shouldnt (I think at last, lol) bring down
// anything if it fails... I am pretty sure there are better ways to do it
try
{
Entry e = new Entry(cat, title, desc, clientIP, path);
mEntryQueue.put( e );
}
catch (InterruptedException ie)
{
success = false;
}
return success;
}
/**
* Private inner class that will be used to run the loggers dedicated
* thread... since I didnīt want to have the run method public for some
* reason, lol
*/
private class LoggerThread implements Runnable
{
@Override
public void run()
{
// Handle exceptions
try
{
// Loop while the thread isnīt interrupted
while (! mLogThread.isInterrupted())
{
Entry e = mEntryQueue.take();
for (LogListener l : mListeners)
l.publish( e );
}
}
catch (InterruptedException ie)
{
System.err.println("ERROR: The logging thread crashed, details:\n" + ie.getMessage());
}
}
}
}
And yes, I like to waste space on comments that isnīt that great :p.