Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Multi-Threading problem

Reply
Thread Tools

Multi-Threading problem

 
 
skoobie
Guest
Posts: n/a
 
      06-17-2008
Hi, this is my first post so please excuse any mistakes. I basically
have scoured over the net and have read many books on Multi-threading
and I am struggling to use it for this problem.

The problem is creating a digitalclock (displaying hours, minutes and
seconds) program which uses a different thread for hours, minutes and
seconds.

Using one thread would not be a problem ( I can do that fine) but
synchronising 3 threads with split second timing is proving to be
difficult. So far I can get the seconds to work but am struggling to
incorporate the minutes and hours.

What I have set out to do is to make hours and mins threads start
first and then wait();
The seconds thread sleeps every one second and set new seconds each
time.
if seconds == 0, notify the minutes thread
The minutes thread then updates minutes and should notify hours when
it reaches 0.

I have written good code for setting the seconds and displaying it. I
am just having problems synchronising the 3 threads. Here is a snipet
of my code:

public void start() {
if (threadS == null) {
threadS = new Thread(new Clock("seconds")); //this, the current
object instance
threadS.setPriority(10); // ensures second starts first
threadS.start();
}
if (threadM == null) {
threadM = new Thread(new Clock("minutes")); //this, the current
object instance
threadM.setPriority(5); // ensures second starts first
// threadM.start();
}

if (threadH == null) {
threadH = new Thread(new Clock("hours")); //this, the current
object instance
threadH.setPriority(2); // ensures second starts first
threadH.start();
}

if (startMins == true) { // flag to start thread
System.err.println("Hello");
threadM.start();
}

/* and in the action part of the code Synchronised method belonging to
run(); */

while (threadS == Thread.currentThread()) {
// setting new seconds code

try {
Thread.sleep(addMilliSec);
} catch (InterruptedException e) { }

if (newSeconds == 00)) {
startMins = true;
start(); // without this threadM doesn't start!
notify();
}

System.out.println(getDigitalClock());
}

while (threadM == Thread.currentThread()) {

minute = newMinutes();
try {
wait();
} catch (InterruptedException e) {}
}
// and so fourth..

The minute increments correctly first time but then I get an
IllegalThreadStateException.
I know why this is.. its because I am trying to start a thread that's
already started before. But if I don't put start() in there.. seconds
continue to update but minutes and seconds don't.

What am I missing?

Any guidance to this would be very helpful. his is very frustrating
because I've got working solutions with one thread but have hit a dead
end trying to use 3.

Thanks for reading,

Skoobie
 
Reply With Quote
 
 
 
 
blmblm@myrealbox.com
Guest
Posts: n/a
 
      06-18-2008
In article <(E-Mail Removed)>,
Lew <(E-Mail Removed)> wrote:
> skoobie wrote:
> > public void start() {
> > if (threadS == null) {

>
> Why would 'threadS' not be null?
>
> > threadS = new Thread(new Clock("seconds")); //this, the current
> > object instance


[ snip ]

> > threadS.setPriority(10); // ensures second starts first

>
> It ensures no such thing.


Indeed. The conventional wisdom (as I understand it) is that
attempting to get proper synchronization by setting thread
priorities is a Bad Idea.

[ snip ]

> > Any guidance to this would be very helpful. his is very frustrating
> > because I've got working solutions with one thread but have hit a dead
> > end trying to use 3.


It might help people suggest solutions if we knew whether the OP's
objective is to learn more about multithreading and synchronization
or to solve some real problem.

> Create a class, possibly an inner class, with a 'run()' method that implements
> Runnable for each of your threads. Have the 'run()' for one do the hours,
> another the minutes, the third the seconds.


Advice seconded, more or less.

> Have them update the state of the
> members of the instance via synchronized setters. Now you never have to check
> if the current thread is the one running - each thread only has one
> responsibility so it knows if it's aware, it's running. The updater threads
> can start timers to trigger updates once per hour, minute and second,
> respectively.


You could do that .... but if the objective is to learn about wait()
and notify(), it seems like it might be more interesting to just have
the seconds-updating thread repeatedly sleep 1 second, and manage
everything else with appropriate use of wait() and notifyAll().

Synchronized getters and setters are not a bad idea in general,
but I wonder whether they might not be overkill here -- for int
variables, marking them "volatile" should be enough to be sure
they actually get updated in memory (rather than being kept in a
register), and with ints there's no risk of simultaneous updates
somehow corrupting internal state, right? (Maybe that's what you
meant below.)

And for this problem you need larger atomic operations anyway,
for example "add one to seconds, and if the result is 60 do
something", no?

> Have another thread handle update of the display, using synchronized getters
> to obtain the values for display.
>
> You could use volatile member values as a way to synchronize.


I put together a semi-hacked-up solution using wait and notifyAll,
which I can post if there's interest. My advice to the OP would
be -- assuming the objective is to learn -- to aim for a solution
where each thread uses, at appropriate times, the standard
mechanism for waiting for a condition to become true:

while (!condition) wait();

and the standard (AIUI) corresponding mechanism for waking up
waiting threads:

condition = true; notifyAll();

It's kind of a fun problem to solve just with wait and notify, IMO.

--
B. L. Massingill
ObDisclaimer: I don't speak for my employers; they return the favor.
 
Reply With Quote
 
 
 
 
blmblm@myrealbox.com
Guest
Posts: n/a
 
      06-19-2008
In article <(E-Mail Removed)>,
Lew <(E-Mail Removed)> wrote:
> http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> > Synchronized getters and setters are not a bad idea in general,
> > but I wonder whether they might not be overkill here -- for int
> > variables, marking them "volatile" should be enough to be sure
> > they actually get updated in memory (rather than being kept in a
> > register), and with ints there's no risk of simultaneous updates
> > somehow corrupting internal state, right?

>
> Lew wrote:
> >> You could use volatile member values as a way to synchronize.

>
> (E-Mail Removed) wrote:
> > (Maybe that's what you meant below.)

>
> Ya think?


Every once in a while, yes. Sometimes I even do so (think) before
posting to Usenet. (Did you mean for your reply to be as snarky as
it's coming across to me?)

> I said synchronized getters and setters, but I didn't explicitly state one had
> to synchronize them with the 'synchronized' keyword, and I mentioned
> 'volatile' specifically to highlight that alternative means of
> synchronizing them.


Yes, you did mention that, but I'd have said that a mention of
"synchronized getters and setters" normally implies use of the
keyword "synchronized", and that the form of synchronization
provided by "volatile" is pretty weak .... Well. This is
quibbling about terminology, and possibly not very important.

Just out of curiosity, your suggestion to use timers -- what do
you envision happening when all three fire more or less at the
same time (as they would once per hour, right?). (And I don't
mean *that* to be as snarky as it might sound.)

I'll add here that I was surprised by Patricia's suggestion to
use a BlockingQueue, but that makes sense too.

--
B. L. Massingill
ObDisclaimer: I don't speak for my employers; they return the favor.
 
Reply With Quote
 
blmblm@myrealbox.com
Guest
Posts: n/a
 
      06-19-2008
In article <(E-Mail Removed)>,
Patricia Shanahan <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> ...
> > I'll add here that I was surprised by Patricia's suggestion to
> > use a BlockingQueue, but that makes sense too.

>
> To me, it seems natural to prefer a message passing interface to shared
> memory with synchronization, given the choice and assuming no
> performance problem. I've spent a lot of time working with explicit
> shared memory, including helping to design shared memory multiprocessor
> systems, but I still find it takes me a lot of thinking to get it right.
>
> In this case, there would be a total of 61 messages per hour, hardly a
> performance issue. I would not roll my own queuing system to do this
> problem that way, but given java.util.concurrent, why not use it?
>


So why did I find it surprising, given that I've probably written a
lot more message-passing code than multithreaded-with-shared-memory
code .... I don't know! and your explanation above generates
another "oh! I didn't think of it that way! but okay ...."
moment, this time about thinking in terms of message passing.
Interesting!

I'm still kind of inclined to think that what to recommend to the OP
depends on the goal (learning versus just-need-to-make-this-work),
but if you want to argue that learning about library classes is at
least as important as learning to roll one's own, I won't argue.
Much, maybe. ?

--
B. L. Massingill
ObDisclaimer: I don't speak for my employers; they return the favor.
 
Reply With Quote
 
Arne Vajhøj
Guest
Posts: n/a
 
      06-20-2008
Lew wrote:
> skoobie wrote:
>> public void start() {
>> threadS = new Thread(new Clock("seconds")); //this, the
>> current
>> object instance

>
> What's with the wide, wide, wide, wide world of TAB indentation?
>
> Two spaces is sufficient indentation for Usenet. What you have is
> harder to read.


Or 4 spaces to follow common practice ...

Arne
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      06-20-2008
On Tue, 17 Jun 2008 15:44:37 -0700 (PDT), skoobie
<(E-Mail Removed)> wrote, quoted or indirectly quoted someone
who said :

>Using one thread would not be a problem ( I can do that fine) but
>synchronising 3 threads with split second timing is proving to be
>difficult. So far I can get the seconds to work but am struggling to
>incorporate the minutes and hours.


That is making it too complicated. All you need is a timer that goes
off sporadically, say every 1/10 second -- nothing accurate needed.
When it wakes up, it gets the precise time, converts it to a String
and pokes it into a Component. There is no need to try to make it go
off exactly every second. That sort of thing will get you in trouble
since any sleeping is only approximate and depends on how busy the
machine is.

See how SetClock entertains you with both running your inaccurate PC
time atomic corrected time.

I did it with an explicit Thread. I could have done it more easily
with a Swing Timer, but that did not exist at the time I wrote the
code.

See http://mindprod.com/webstart/setclock.html

http://mindprod.com/jgloss/timer.html
--

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
Reply With Quote
 
Knute Johnson
Guest
Posts: n/a
 
      06-20-2008
skoobie wrote:
> Hi, this is my first post so please excuse any mistakes. I basically
> have scoured over the net and have read many books on Multi-threading
> and I am struggling to use it for this problem.
>
> The problem is creating a digitalclock (displaying hours, minutes and
> seconds) program which uses a different thread for hours, minutes and
> seconds.
>
> Using one thread would not be a problem ( I can do that fine) but
> synchronising 3 threads with split second timing is proving to be
> difficult. So far I can get the seconds to work but am struggling to
> incorporate the minutes and hours.
>
> What I have set out to do is to make hours and mins threads start
> first and then wait();
> The seconds thread sleeps every one second and set new seconds each
> time.
> if seconds == 0, notify the minutes thread
> The minutes thread then updates minutes and should notify hours when
> it reaches 0.
>
> I have written good code for setting the seconds and displaying it. I
> am just having problems synchronising the 3 threads. Here is a snipet
> of my code:
>
> public void start() {
> if (threadS == null) {
> threadS = new Thread(new Clock("seconds")); //this, the current
> object instance
> threadS.setPriority(10); // ensures second starts first
> threadS.start();
> }
> if (threadM == null) {
> threadM = new Thread(new Clock("minutes")); //this, the current
> object instance
> threadM.setPriority(5); // ensures second starts first
> // threadM.start();
> }
>
> if (threadH == null) {
> threadH = new Thread(new Clock("hours")); //this, the current
> object instance
> threadH.setPriority(2); // ensures second starts first
> threadH.start();
> }
>
> if (startMins == true) { // flag to start thread
> System.err.println("Hello");
> threadM.start();
> }
>
> /* and in the action part of the code Synchronised method belonging to
> run(); */
>
> while (threadS == Thread.currentThread()) {
> // setting new seconds code
>
> try {
> Thread.sleep(addMilliSec);
> } catch (InterruptedException e) { }
>
> if (newSeconds == 00)) {
> startMins = true;
> start(); // without this threadM doesn't start!
> notify();
> }
>
> System.out.println(getDigitalClock());
> }
>
> while (threadM == Thread.currentThread()) {
>
> minute = newMinutes();
> try {
> wait();
> } catch (InterruptedException e) {}
> }
> // and so fourth..
>
> The minute increments correctly first time but then I get an
> IllegalThreadStateException.
> I know why this is.. its because I am trying to start a thread that's
> already started before. But if I don't put start() in there.. seconds
> continue to update but minutes and seconds don't.
>
> What am I missing?
>
> Any guidance to this would be very helpful. his is very frustrating
> because I've got working solutions with one thread but have hit a dead
> end trying to use 3.
>
> Thanks for reading,
>
> Skoobie


Here's my entry for the "Strange Clock" contest. I used listeners to
notify the minutes and hours to increment. I liked Patricia's idea of a
blocking queue but that seemed too simple.

You need to set this clock. Enter a value in the hours/minutes field
and press <ENTER> to update the counter. The seconds field is reset to
00 when <ENTER> is pressed.

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

public class StrangeClock extends JPanel {
public StrangeClock() {
final ClockField seconds = new ClockField(60);
final ClockField minutes = new ClockField(60);
final ClockField hours = new ClockField(24);

new javax.swing.Timer(1000,new ActionListener() {
public void actionPerformed(ActionEvent ae) {
seconds.increment();
}
}).start();

seconds.addRollOverEventListener(new RollOverEventListener() {
public void rollOverEventOccurred(RollOverEvent roe) {
minutes.increment();
}
});

minutes.addRollOverEventListener(new RollOverEventListener() {
public void rollOverEventOccurred(RollOverEvent roe) {
hours.increment();
}
});

seconds.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
seconds.clear();
}
});

minutes.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
minutes.set();
}
});

hours.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
hours.set();
}
});

add(hours);
add(new JLabel(":"));
add(minutes);
add(new JLabel(":"));
add(seconds);
}

public class RollOverEvent extends EventObject {
public RollOverEvent(Object source) {
super(source);
}
}

public interface RollOverEventListener extends EventListener {
public void rollOverEventOccurred(RollOverEvent roe);
}

public class ClockField extends JTextField {
private int count;
private final int limit;
protected EventListenerList eList = new EventListenerList();

public ClockField(int limit) {
super("00");
this.limit = limit;
}

public void increment() {
if (++count == limit) {
fireRollOverEvent(new RollOverEvent(this));
count = 0;
}
setText(String.format("%02d",count));
}

public void clear() {
count = 0;
setText(String.format("%02d",count));
}

public void set() {
try {
count = Integer.parseInt(getText());
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
setText(String.format("%02d",count));
}

public void addRollOverEventListener(
RollOverEventListener listener) {
eList.add(RollOverEventListener.class,listener);
}

public void removeRollOverEventListener(
RollOverEventListener listener) {
eList.remove(RollOverEventListener.class,listener) ;
}

void fireRollOverEvent(RollOverEvent roe) {
Object[] listeners = eList.getListenerList();
for (int i=0; i<listeners.length; i+=2)
if (listeners[i] == RollOverEventListener.class)

((RollOverEventListener)listeners[i+1]).rollOverEventOccurred(roe);
}
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame("Strange Clock");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
StrangeClock sc = new StrangeClock();
f.add(sc,BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
});
}
}

--

Knute Johnson
email s/nospam/knute2008/

--
Posted via NewsDemon.com - Premium Uncensored Newsgroup Service
------->>>>>>http://www.NewsDemon.com<<<<<<------
Unlimited Access, Anonymous Accounts, Uncensored Broadband Access
 
Reply With Quote
 
JK
Guest
Posts: n/a
 
      06-22-2008
skoobie wrote:

[snip]

The code you posted does not look like it was written by a person who
has scoured the 'net and read multiple books about multithreading. It
kinda looks like homework, in fact; apologies if I'm wrong about that.
Anyway, I'll try to get you going.

I assume you want to use three threads because you want to learn how to
get multiple threads to interact, not because you think three threads
are actually necessary to solve this problem. So let's just establish
the data that we need, and start three threads, one for updating each
time interval. These threads do nothing but sleep; the point is just to
start them.

public class MyClock {

private int seconds=0;
private int minutes=0;
private int hours=0;

private void secondsThread() {
while (true) {
try {Thread.sleep(1000);} catch (InterruptedException ex) {}
System.out.println("The current time is: "+
seconds+':'+minutes+':'+hours);
}
}

private void minutesThread() {
while (true) {
try {Thread.sleep(1000);} catch (InterruptedException ex) {}
System.out.println("Minute thread woke up.");
}
}

private void hoursThread() {
while (true) {
try {Thread.sleep(1000);} catch (InterruptedException ex) {}
System.out.println("Hour thread woke up.");
}
}

public static void main(String[] args) {
final MyClock myClock=new MyClock();

// Start the seconds thread. We'll use the usual idiom of an
// anonymous Runnable to execute a method on myClock in a
// new thread. We don't care about the actual Thread instances;
// all of them can just run forever.
new Thread(new Runnable() {
public void run() { myClock.secondsThread(); }
}).start(); // Don't forget to start the thread!

// Start the minutes thread.
new Thread(new Runnable() {
public void run() { myClock.minutesThread(); }
}).start();

// Start the hours thread. We'll just use the main()
// thread for this.
myClock.hoursThread();
}

}

OK. Invoking MyClock.main() will now create a MyClock instance and call
each of its secondsThread(), minutesThread(), and hoursThread() methods
in different threads.

So what do we want these threads to do? I'm not going to solve that
problem for you right now. You will need to think carefully about the
conditions under which you want each thread to wake up and update the
seconds, minutes, and hours member variables. Here's a hint: it should
not matter in what order the threads start; it should only matter that
they wake up and do their appointed jobs when the appropriate conditions
occur.

Hope this helps.

-- JK

--
(declare (antichrist i) (anarchist i)) ; -- the sexp-pistols
 
Reply With Quote
 
blmblm@myrealbox.com
Guest
Posts: n/a
 
      06-26-2008
In article <(E-Mail Removed)> ,
Patricia Shanahan <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > In article <(E-Mail Removed)>,
> > Patricia Shanahan <(E-Mail Removed)> wrote:
> >> (E-Mail Removed) wrote:
> >> ...
> >>> I'll add here that I was surprised by Patricia's suggestion to
> >>> use a BlockingQueue, but that makes sense too.
> >> To me, it seems natural to prefer a message passing interface to shared
> >> memory with synchronization [ .... ]


> > So why did I find it surprising, given that I've probably written a
> > lot more message-passing code than multithreaded-with-shared-memory
> > code .... [ .... ]


> I think this may be a consequence of Java's initial lack of built-in
> support for thread communication approaches other than shared memory
> with synchronization. We all got used to using that directly, rather
> than treating it as a low level facility that should be used mainly to
> build conventional structures such as message passing and semaphores.
>
> I've been trying to practice considering java.util.concurrent before
> working with shared memory directly, but it's a difficult habit to change.


Belatedly following up to say that you're probably exactly right
about why my first inclination seems to involve using the low-level
stuff, and that the implicit suggestion to make a conscious effort
to use the new stuff is a good one!

> Incidentally, the problem could also be solved using a pair of
> semaphores. For example, the minutes thread would acquire from a
> semaphore, and the seconds thread would release the semaphore each time
> its counter wraps.


Oh yeah, you could ....

I thought about posting my semi-hacked-up solution for comments,
but maybe not. But it was interesting to see how many different
ways people came up with of approaching this problem.

[ snip ]

> I am sure this is a learning exercise of some sort, because the single
> thread implementation is obviously simpler and at least as effective as
> the multi-threaded one.
>
> The issue is whether the objective is to learn to use shared memory and
> synchronization directly, or to learn to write multi-threaded code in
> Java as it is now.


Yeah ....

I wonder whether at some point the OP will come back and tell
us what the objective was, and whether any of the suggestions
were helpful.

--
B. L. Massingill
ObDisclaimer: I don't speak for my employers; they return the favor.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Problem problem problem :( Need Help Mike ASP General 2 05-11-2004 08:36 AM



Advertisments