• Post Reply Bookmark Topic Watch Topic
  • New Topic

Advice on simple threadding...

 
Ivan Jouikov
Ranch Hand
Posts: 269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi!
I am working on a Logger. The system is simple. You have loggers - Console, file, Html, etc. You have log managers - SimpleLogManager, ThreadedLogManager, TimedLogManager. Here's a code snippet:

Everything works fine... but I am not sure how fine it works...
I was working on ThreadedLogManager. What I want it to do is to handle all the logging in a background thread. So here's what my ThreadedLogManager looks like so far:

It seems to log just fine, but whenever my main() is finished executing, I still see my proccess running in my IDE's (NetBeans 3.5) execution window... And if I try to do System.exit(0); at the end of my main, nothing gets logged at all (not unless I do Thread.sleep(1000) before exiting)...
So can you tell me what my problem is? And give some advice perhaps?
Thank you in advance,
Ivan Jouikov.
 
John Smith
Ranch Hand
Posts: 2937
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, I see a few problems with your logger. First, you have an infinite loop in your run() method which you probably break by issuing the interrupt(). This is not a recommended way to terminate the threads. Rather, have a boolean that you can set to indicate that the thread should finish.
The other problem is that you have a busy loop in your run() that will waste a lot of CPU cycles. The standard solution here is to use the wait()-notify() mechanism. That is, when a new message arrives, you notify() the logger, and after the message is logged, the logger should wait().
 
Ivan Jouikov
Ranch Hand
Posts: 269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I thank thee, oh mighty wizard!
I shalt try that and report shortly with the results!
Again thank thee!
 
Ivan Jouikov
Ranch Hand
Posts: 269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok I made some modificiations.. here's what it looks like now:

Whenever I run it, the first message gets logged properly, and right after that (on the second message?) I get the following:


... and my thread seems to keep on running... can u tell me where my problem is?
 
Ivan Jouikov
Ranch Hand
Posts: 269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK after some reading and thinking, here's what I came up with:

Since I am new to threading, I will try to explain what I think of this, and can you please correct me if I am wrong?
Ok, so what happens when this class gets first constructed is:
- we create a background thread with minimal priority and run it...
- It immediately jumps into the run() method
- There it creates a monitor for the messages queue (synchronized(messages))
- Since !done == true, it runs through the code until it reaches wait() line ( since everything is empty )
- it puts a wait() on messages monitor... so the writeThread gets "suspended" (1.CORRECT?)

Ok whenever we want to log something ( log() ):
- first we reach the monitor ( synchronized(messages) ), and we will wait until the background thread is finished logging. ( 2.Is this efficient btw? won't that create a bottleneck which will make the whole threading useless? Or will it work since writeThread has lower priority? )
- We'll put the level of logging and the data into the queue.
- we'll notify the messages monitor that it is ready to log ( 3. CORRECT? )
Ok now once we notified it, the messages.wait() in run() should return and our loop will continue:
- we make sure that queue is not empty ( 4.would it be OK to have if() instead of while()? or does while() provide more "safety"?)
- we'll retrieve data from the queue and dispatch it to each individual logger

do I sound correct? Because whenever my program is finished running, NetBeans still shows it in the porccess list...
 
John Smith
Ranch Hand
Posts: 2937
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
do I sound correct? Because whenever my program is finished running, NetBeans still shows it in the porccess list...
You still have an infinite loop, because the only way to terminate it would be to either call the interrupt() (which you probably don't call anymore) or setting the boolean "done". That boolean, however, is set in the finalize() method that is not guaranteed to execute. You should never rely on the finalize().
The standard way to handle the thread termination it to declare your boolean as volatile, and have a method that can set it, whenever you want to terminate the thread gracefully.
I'll get to your other question later (unless someone else steps in).
 
Dirk Schreckmann
Sheriff
Posts: 7023
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Moving this to the Threads and Synchronization forum...
 
Ivan Jouikov
Ranch Hand
Posts: 269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But even if I declare that variable as violatile (can you explain what its for?), how would I terminate it AUTOMATICALLY, whenever JVM terminates or it gets GC?
Cause it'd be VERY incovinient for a user to turn off that logger manually at the end of the program...
 
Ivan Jouikov
Ranch Hand
Posts: 269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was also thinking...
that instead of having a background logging thread running forever and logging data that is in the queue,
I could have a NEW thread created every time some data has been enqueued, and have that thread as a background thread... So for every piece of data I'd have its own background thread...
This would seem to solve my problem cause I'd not have 2 have an infinite loop... but doesn't it take a lot of resources to allocate a new thread every time I want to log something?
 
John Smith
Ranch Hand
Posts: 2937
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are getting closer. However, if you want to do it the right way, I would recommend that you get some background information.
A good source is Java Thread Programming by Paul Hyde.
And if you really want to understand what thread programming is all about, try Concurrent Programming in Java by Doug Lea.
- we create a background thread with minimal priority and run it...
It's not recommended to manipulate the priorities. One of the many reasons is that the Java range of priorities (from min to max) doesn't map well into the OS thread priorities.
- it puts a wait() on messages monitor... so the writeThread gets "suspended" (1.CORRECT?)
More precisely, the thread is put in the "wait" state.
- first we reach the monitor ( synchronized(messages) ), and we will wait until the background thread is finished logging.
Good.
2.Is this efficient btw? won't that create a bottleneck which will make the whole threading useless? Or will it work since writeThread has lower priority? )
No matter how you turn it around, you cannot both write and read from the same resource. But in your case, I would not expect a bottleneck because your "((Logger)iterator.next()).log( level, data )" operation is presumably a matter of milliseconds. But even if it was singificantly longer, it would still be beneficial, because you could still coninue running your app without waitng until the log operation completes.
Incidentally, I don't see where you dequeue the messages, -- is there a reason that you write the same messages over and over again?

- we'll notify the messages monitor that it is ready to log ( 3. CORRECT? )
Yep.
But even if I declare that variable as violatile (can you explain what its for?)
The concept of "volatile" deserves its own thread, but I am sure you will get a few hits if you search for in in this forum.
how would I terminate it AUTOMATICALLY, whenever JVM terminates or it gets GC?
Well, something happens before your program terminates, right? You probably click some "Exit" menu item at which point you must be doing some clean up. As part of that clean-up, call the method on your object that sets the boolean and terminates the thread.
I was also thinking...
that instead of having a background logging thread running forever and logging data that is in the queue, I could have a NEW thread created every time some data has been enqueued, and have that thread as a background thread... So for every piece of data I'd have its own background thread...

Certainly possible, that's a matter of your requirements and the design.
 
Steve Lovelace
Ranch Hand
Posts: 125
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I believe you can have the JVM take down the thread automatically simply by declaring to be a daemon. You do this with setDaemon(true), and you must invoke it on the thread before start(). The logic of the JVM is that when all non-daemon threads have died, it quits.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!