Thread View: comp.lang.java.programmer
3 messages
3 total messages
Started by Kim Frederiksen
Tue, 23 Mar 1999 00:00
The best synchronized Paint!
Author: Kim Frederiksen
Date: Tue, 23 Mar 1999 00:00
Date: Tue, 23 Mar 1999 00:00
47 lines
1944 bytes
1944 bytes
Hi Everybody,
I've been working on getting my paint synchronized as good as possible,
this is what I've come up with, can you think of something that would
work even better, let me know :-)
Kim Frederiksen
int currentTime;
int lastTime;
int appletSpeed=30; // Max wait time in milliseconds
public void start()
{
startTime=(int) System.currentTimeMillis();
}
synchronized public void run ()
{
while (true)
{
repaint();
try
{
wait();
}
catch(InterruptedException e) { }
currentTime=((int) System.currentTimeMillis())-startTime;
sleepTime=(lastTime+appletSpeed)-currentTime;
lastTime=currentTime;
if(sleepTime>0)
{
try
{
spinThread.sleep(sleepTime);
}
catch(InterruptedException e) { }
}
lastTime=((int) System.currentTimeMillis())-startTime;
}
}
synchronized public void paint(Graphics g)
{
notifyAll();
}
Re: The best synchronized Paint!
Author: David Holmes
Date: Wed, 24 Mar 1999 00:00
Date: Wed, 24 Mar 1999 00:00
89 lines
3994 bytes
3994 bytes
Kim Frederiksen wrote in message <36F75CF1.37367641@greydirect.dk>...
>I've been working on getting my paint synchronized as good as possible,
>this is what I've come up with, can you think of something that would
>work even better, let me know :-)
If you *really* think you need to do this then you should make some changes.
First off repaint() results in update() being invoked so put the
notification in there. That way you don't synchronize paint() which is
invoked much more often than update.
However a warning. repaint() is not guaranteed to have update() invoked as
the system can swallow the repaint request if it decides that nothing needs
repainting. To combat this use a timed version of wait().
Don't synchronize run() as that will prevent paint() from being invoked even
when your thread is sleeping. Simply use a synchronized block of an
appropriate form.
You should always wait() in a loop, to avoid problems with spurious
wakeups - though in this case you don't care that much.
Use long's not int's otherwise you'll have problems on machines that
actually stay up for a reasonable length of time. :)
Your timing logic could be simpler. You want to see if the elapsed time is
greater than the 'interval' and if not you want to sleep for the difference.
Below is a revised version of your code. Note that all this timing stuff is
pretty loose anyway as scheduling can make your calculations meaningless.
Given that its not surprising that most simple animations just do a
repaint() followed by a sleep().
David
------------------------------------------
long appletSpeed=30; // Max wait time in milliseconds
int signals = 0; // flag to signal repaint has been done
long timeout = 2000; // timeout incase repaint() gets ignored
public void run (){
long lastPaint = 0;
while (true){
mainloop:
lastPaint = System.currentTimeMillis();
repaint();
synchronized(this){
int origSignals = signals;
while(true){
try { wait(timeout); } catch(InterruptedException ie){}
// either signalled or timedout or spurious
if (origSignals != signals) break; // notified
else {
long now = System.currentTimeMillis();
if (now - lastPaint > timeout)
// we timed out which probably means the repaint
// was ignored, so restart the main loop
continue mainloop;
}
// else spurious so re-wait
}
}
}
// we were signalled so see if enough time has elapsed
// since the last repaint
long now = System.currentTimeMillis();
long sleepTime = (now - lastPaint) - appletSpeed;
if(sleepTime>0){
try {
Thread.sleep(sleepTime);
}
catch(InterruptedException e) { }
}
}
}
public void update(Graphics g){
paint(g);
synchronized(this){
signals++;
notifyAll(); // notify() will do if only ever one thread
}
}
public void paint(Graphics g){
// paint as appropriate
}
Re: The best synchronized Paint!
Author: David Holmes
Date: Sat, 27 Mar 1999 00:00
Date: Sat, 27 Mar 1999 00:00
69 lines
2893 bytes
2893 bytes
David Holmes wrote in message <7d9jcc$ki5$1@sunb.ocs.mq.edu.au>...
> while (true){
>mainloop:
> lastPaint = System.currentTimeMillis();
> repaint();
> synchronized(this){
> int origSignals = signals;
The above is incorrect. My apologies. That's what happens when you write
these things on the fly.
In the above the the event thread could complete the execution of update()
in response to the repaint() before the above thread has starting waiting -
a classic lost wakeup problem (though the timeout would stop the thread from
hanging). A correct version is given below.
David
---------------------
public void run (){
long lastPaint = 0;
while (true){
mainloop:
synchronized(this){
lastPaint = System.currentTimeMillis();
repaint();
int origSignals = signals;
while(true){
try { wait(timeout); } catch(InterruptedException ie){}
// either signalled or timedout or spurious
if (origSignals != signals) break; // notified
else {
long now = System.currentTimeMillis();
if (now - lastPaint > timeout)
// we timed out which probably means the repaint
// was ignored, so restart the main loop
continue mainloop;
}
// else spurious so re-wait
}
}
}
// we were signalled so see if enough time has elapsed
// since the last repaint
long now = System.currentTimeMillis();
long sleepTime = (now - lastPaint) - appletSpeed;
if(sleepTime>0){
try {
Thread.sleep(sleepTime);
}
catch(InterruptedException e) { }
}
}
}
public void update(Graphics g){
paint(g);
synchronized(this){
signals++;
notifyAll(); // notify() will do if only ever one thread
}
}
public void paint(Graphics g){
// paint as appropriate
}
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads