• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Devaka Cooray
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Jeanne Boyarsky
  • Tim Cooke
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Tim Moores
  • Mikalai Zaikin
  • Carey Brown
Bartenders:

Simple test program: Why isn;t Runnable running in the new Thread ?

 
Ranch Hand
Posts: 103
3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello, I'm applying what I've learned about guarded blocks with a simple app.

PrintWeather object waits until DecideTheWeather, which is running in a new thread, has notified all other threads.
However I can't work out why the second thread is not executing.

Class SharedWeatherData defines :
  • shared data: static String weather and static boolean hasTheWeatherBeenDecided


  • Class DecideTheWeather:
  • decides the weather and updates the weather and boolean flag in SharedWeatherDatashared


  • Class PrintWeather:
  • prints the weather if the weather has been decided


  • Class WeatherProgram contains the main method.










     
    Marshal
    Posts: 28009
    94
    Eclipse IDE Firefox Browser MySQL Database
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    You're asking why line 24 in WeatherProgram does not run, I think. (Let me know if I'm wrong.) Well, it can't run until line 7 completes, and I don't think it ever does.

    It's been a very long time since I had to use code which uses threads like this, so I had to look up what the wait() method does.
     
    Mohammed Azeem
    Ranch Hand
    Posts: 103
    3
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Good Evening Paul,

    I have a horrible sense that I've made a logical mistake in this pattern of inter-thread communication.
    To all readers, I will look into it again tomorrow and promise a full answer.

    First thoughts on you remarks Paul: the intended flow control was as follows:

  • The PrintWeather and DecideTheWeather have access to shared data.  PrintWeather must not proceed until the shared data is written to. So, it waits for decideTheWeather to do so.
  • line 7: main method acquires lock for weatherPrinter by calling weather.printTheWeather() - a synchronized method
  • line 17: wait() - the main thread voluntarily suspends itself, thereby relinquishing the lock on shared data - the boolean flag weatherHasBeenDecided. It needs to release itself so that the second thread can access the flag
  • line 24 -25 in WeatherDecider:  the shared data has been set, the second thread notifies all other threads
  • now, that the main thread is sure that shared data has been set it resumes its run.

  • .
     
    Paul Clapham
    Marshal
    Posts: 28009
    94
    Eclipse IDE Firefox Browser MySQL Database
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Here's what the wait() method does:

    The documentation wrote:Causes the current thread to wait until it is awakened, typically by being notified or interrupted.

    Since the thread is waiting, it won't be able notify itself that it can continue.

    So yeah, a redesign would be a good idea.
     
    Paul Clapham
    Marshal
    Posts: 28009
    94
    Eclipse IDE Firefox Browser MySQL Database
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I think part of the trouble is this: You have defined a process which looks like "Do Thing A, then when that's finished Do Thing B". There's really no need to use more than one thread to execute that process. That's not to say you must not use more than one thread, but it does mean that it's going to be hard to twist it into something which does use more than one thread.
     
    Saloon Keeper
    Posts: 15276
    350
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I think the program is supposed to demonstrate two threads interacting with each other. The problem is that in this case, one of those threads is initializing the other thread. This is a brittle setup.

    You can fix the problem by making the main thread responsible only for setting up and starting the two threads. Importantly, the main thread must NOT call any blocking methods.

    There are other issues with your code that are not directly related to your current issue:

  • Do not instantiate and start threads directly. Instead, use an ExecutorService.
  • NEVER use static fields to communicate application state between two classes. Static fields must be used for constant values only.

  • All of your issues can be solved elegantly like this:

    In the future, you will be able to do something like this instead:
     
    Greenhorn
    Posts: 16
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Nice program.  How will you tell what the weather is like?  Some other data.  Like a Input/Ouptstream file some where reading the data base.  Would this location or reading work on a program like this.  This is on your home pc or work.  
     
    Saloon Keeper
    Posts: 27494
    195
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Dean Sabado wrote:Nice program.  How will you tell what the weather is like?  Some other data.  Like a Input/Ouptstream file some where reading the data base.  Would this location or reading work on a program like this.  This is on your home pc or work.  


    I cannot speak for OP, but I get my weather data from the US National Weather Service API. Equivalents exist for other countries.

    A note: making public static variables is not a recommended practice, and doubly-so in a multi-threaded environment. As a general rule, it's best not to be static at all, and if so, to use synchronized accessor methods.
     
    Mohammed Azeem
    Ranch Hand
    Posts: 103
    3
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Apologies for the delay in my reply, I code as a hobby in the evenings after my day job.

    After much re-study I am now able to identify the faults in the original program and offer a solution that works.

    The weather program was a way of modelling inter-thread cooperation:
  • Two threads sharing the same data (the simplest data structure – a class with field variables and getters/setters)
  • Establsihing a happens – before relationship between two tasks. One thread’s execution to be contingent upon the second thread completing a required task.
    In the weather program, the weather cannot be printed until the decider has decided what it is going to be.


  • This requires the two threads to share the same monitor (synonymous to ‘lock’).
    The lock can be provided by any object, but a convenient object is an instance of Java Object, since it is only its lock we’re interested in.

    If like me, you are highly visual, I have attached a sort of flow diagram that shows two threads sharing the same lock in a happens – before relationship.
    I explain it as follows:

    The first thread acquires the lock and its task (the WeatherPrinter) checks whether a
    Boolean flag has been set by the second thread running the WeatherDecider

    If not:
  • It calls wait() allowing the second thread to acquire the monitor’s lock.
  • The second thread’s task (WeatherDecider) can then decide the weather and set the flag to show it has been decided.
    The task then issues a notify() on the monitor and releases the lock.
  • The first thread re-aquires the lock (remember it’s the same lock)
  • It sees that the weather flag is set and proceeds to print the weather.


  • If yes:
  • It reads the weather string and prints it.


  • Is the data in WeatherData, guarded from being changed by objects other than WeatherData?  I believer so.
    The object reference weatherData is declared final, meaning that it will always refer to a single unique WeatherData object.
    Therefore, passing the weatherData reference always passes the same object.

    Finally, thank you for taking an interest in the post. Maybe I should payback by responding to other people's posts. But I implore you gently - please make your code readable, it's half the battle !

    Class WeatherData


    Class WeatherPrinter


    Class WeatherDecider


    Main method class


    Typical output:


     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15276
    350
    • Likes 1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Yes, your code is correct.

    I have a few comments to help you improve your code though:

  • Make your classes final unless you have a good reason not to.
  • Don't make your classes and methods public unless you have a good reason. Making them public by default is a bad habit.
  • Make your fields private.
  • You can remove the hasWeatherBeenDecided field by relying on a null value for weather instead.
  • Validate your constructor and method parameters.
  • Prefer enum constants over string constants.
  • Don't catch exceptions unless you have a good way of handling them.
  • You can use Callable instead of Runnable to throw exceptions from a task.
  • Instead of creating services like Random on the fly, inject them into your constructors.
  • Don't print to System.out unless it's part of your business logic. Use loggers instead.
  • You can simplify your application a little bit by moving your synchronization from your runnables to the WeatherData class.
  • Using monitors and wait() and notify() is a bit old-fashioned. These days we prefer locks and conditions.
  • Use an executor service instead of creating your threads manually.





  •  
    Mohammed Azeem
    Ranch Hand
    Posts: 103
    3
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thank you Stephan,

    I'll read up on  ENUMS - I'm aware of them but have neglected them.
    Yes, I'm in the bad habit of declaring fields public - inexplicable really.
    I'll study your use of the Executor service .
     
    If you believe you can tell me what to think, I believe I can tell you where to go. Go read this tiny ad!
    a bit of art, as a gift, the permaculture playing cards
    https://gardener-gift.com
    reply
      Bookmark Topic Watch Topic
    • New Topic