• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

MultiThreading and Sharing Resources

 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi All,

First time poster and java n00b. In short, I'm having difficulty in where to go (and resolve the errors) I'm having with a certain program I have to make for an assignment. Basically it is thus;

** Tom, Dick and Harry are fishing at a nearby lake.
** Unfortunately they only brought two fishing rods, so they each must share.
** When they catch a fish, they clean it and put it into the storage box before returning to fish.

I have to show threads using both the Runnable interface and extension of the Thread class (there's other bits, like showing concurrency errors, how it was avoided and synchronisation but I will get to that when I finish this part).

So far I have three seperate classes; FishingRod, Lake & TestThread.

TestThread

Lake

Fishing Rods



Not even mentioning the linkage issues (i.e. not being able to find the FishingRod[Rods] array in the FishingRod class that is declared in the TestThread class as one example) and not knowing how to actually share the resources of the fishing rods, I am hoping someone with a lot more experience than me can show me what the next steps are and how to fix this existing mess.

My Eclipse is having heart trouble based on all those red X's at the side!

Appreciated!
 
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to the Ranch

Never, never, never use == true and == false. Not only are they poor style, but also the compiler won’t always notice if you make the mistake of writing = instead of ==.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Why have you given the Lake a static field and static methods?
Your loop which counts how many fish you have looks suspect. If you have 12 fish, that loop will run 12 times. But what if somebody else catches a fish while that loop is running? I would suggest you add a hasFish() or isEmpty() method (but not both) to the Lake class, which would help with that loop.
Your exercise looks like a classic exercise called dining philosophers by Tony Hoare, publicised by Edsger Dijkstra. You can find out about it on the net. You can also find something in the Java Tutorials; look for the sections about deadlock and livelock.

When you go on about arrays of rods, and you actually have a List of rods, that suggests to me you are trying to do too much at once. You need to break down the application into tiny pieces, and get each little piece working before you try the next piece.
You also need to consider which resources are in demand, and which would need a Lock applying. Once you have done that, work out how to apply the Lock and where. Then you can work out how to share out access to that resource when it is unlocked.
 
Bren Reggy
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Why have you given the Lake a static field and static methods?



Eclipse kept telling me it could not make a static reference from a non-static variable everytime I tried to initiate the method via the run().

I tried breaking down the problem into little bits but I'm still confused. I keep looking over the Five Philosophers problem to compare but I'm trying to avoid straight copying.
 
Bren Reggy
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Amended slightly. Showing the errors in the comments



Everytime I make the method static to satisfy the static reference, I get another error stating that static methods can only be declared in a static or top level type. Compiler error states:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The constructor Fishing.FishingRod(int) is undefined
Type mismatch: cannot convert from Fishing.FishingRod to Fishing.FishingRod[]

at fishing.Fishing.main(Fishing.java:56)


I have a feeling it hasn't picked up on the static reference errors until the other error is resolved.

It's probably something silly I can't see so If anyone can show what I'm doing wrong, it'll be appreciated.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think you are trying too many things all at once. You need to break your application into smaller pieces and get each piece working before you try to put them together.
I suggest you get your Lake class working, so you can have a Lake object with fish in (ie get rid of the static modifiers throughout), and get that working. Run two threads which remove fish. Consider what concurrency problems you are going to have.

And you need to create Lake objects. Give the Lake a name and number of fish, so you can create an instance with the new operator. Run it with two threads which remove different numbers of fish. Give your Lake class a toString() and display it.The compiler error means that you are not matching the constructor calls to the form of the constructor correctly.

Get that bit working and forget about the rest until later.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You also ought to put Lake in its own class and its own file. You have got the indentation right, which makes the problem obvious.
Similarly the rod class. Why are they inner classes?

[edit]Add 2nd line[/edit]
 
Bren Reggy
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You were right with focusing on one class at a time and I feel I have made good headway. So far I have;

Lake Class


Fishing Rod Class


and the prime class Fishing Class


My problem is now the threads each instantiate a seperate FishingRod and Lake object (as if they each are fishing in their own lakes!). It is obvious that this is cause the Lake and Rod constructors are in the run() method. I have tried to move this to the main() but the problem is that the run() doesn't recognise "thisLake" object when it's been created in the main(). Probably a silly overlook but how would I resolve this error?
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well done so far

You should remove all mention of threads from the Lake class. That is a shared resource, so you shouldn’t care at this stage which thread catches a fish. Think in real life: you have several people catching fish in the same lake. The change is that the lake loses fish (until you put them back), but it cannot tell who has caught what.
Get that Lake class working in a one-threaded environment where you have one Fisher and one Rod.
Some other changes I would suggest:
  • Your isEmpty method should return a boolean which tells you whether you have 0 fish left. Nothing else.
  • You can simplify the method which removes fish to this: fish--; You don’t need the assignment.
  • You can probably lose the newFishAmount field altogether. You are not using it at all.
  • Your getXXX methods should return whatever they get. The getLakeName method should return the name of the lake, and if you want to display it you should write a displayLakeName method.
  • I recommend you write the standard methods for all objects, at least toString.
  • I think the field would be better called name than lakeName, you don’t need a reminder that you are in the Lake class.
  • I cannot make similar comments about the Rod and Fisher classes, mainly because I haven’t bothered to read them! I presume the many print statements are there for testing and debugging use (good idea ) and you won’t use them in the final product.

    Now, this is the hard bit. Consider what changes you would have to make to the Lake class to make it safe for threaded use. Consider which if its fields will change and which not. If any fields don’t change, can you make them final and avoid any threading problems for those fields. If any fields are going to change, how can you make access to them safe for threaded use.
     
    Campbell Ritchie
    Marshal
    Posts: 79177
    377
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Bren Reggy wrote: . . . My problem is now the threads each instantiate a seperate FishingRod and Lake object (as if they each are fishing in their own lakes!). It is obvious that this is cause the Lake and Rod constructors are in the run() method. I have tried to move this to the main() but the problem is that the run() doesn't recognise "thisLake" object when it's been created in the main(). Probably a silly overlook but how would I resolve this error?

    Ignore it for the time being.

    Get a single-threaded application working with one fisher, one rod and one Lake. I have already suggested what to do about the Lake class. Apply the same considerations to the Fisher and Rod classes. I presume you have some method of working out which Fisher has a Rod, when he picks up and replaces the Rod, and when it is or is not available for somebody else to take a turn.
    Work out how to make the Fisher and Rod classes applicable for a multi-threaded environment. Then see whether that error you complained of still applies; there is a good chance of its vanishing or being solved in the meantime.
     
    Bren Reggy
    Greenhorn
    Posts: 12
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Campbell Ritchie wrote:
    You should remove all mention of threads from the Lake class. That is a shared resource, so you shouldn’t care at this stage which thread catches a fish. Think in real life: you have several people catching fish in the same lake. The change is that the lake loses fish (until you put them back), but it cannot tell who has caught what.



    Okay, removed all thread references from the Lake and FishingRod classes

    Campbell Ritchie wrote:
    Get that Lake class working in a one-threaded environment where you have one Fisher and one Rod.



    I have the lake and rod class working in conjunction with the Fishing class. The Fishing class is where the threads (fishers) and all objects are instantiated, calling upon FishingRod and Lake class. They work easily with one thread and three threads, but they are not sharing the resources (i.e. 1 lake and 1 rod across the three threads)

    Campbell Ritchie wrote:
    Some other changes I would suggest:

  • Your isEmpty method should return a boolean which tells you whether you have 0 fish left. Nothing else.



  • I see the reasoning and have done so.

    Campbell Ritchie wrote:

  • You can simplify the method which removes fish to this: fish--; You don't need the assignment.



  • Also done

    Campbell Ritchie wrote:

  • You can probably lose the newFishAmount field altogether. You are not using it at all.



  • I now understand why and it's also done.

    Campbell Ritchie wrote:

  • Your getXXX methods should return whatever they get. The getLakeName method should return the name of the lake, and if you want to display it you should write a displayLakeName method.



  • Understood and done.

    Campbell Ritchie wrote:

  • I recommend you write the standard methods for all objects, at least toString.



  • At the risk of sounding unintelligent, I do not understand what you mean by this?

    Campbell Ritchie wrote:

  • I think the field would be better called name than lakeName, you don't need a reminder that you are in the Lake class.



  • Done.

    Campbell Ritchie wrote:
    I cannot make similar comments about the Rod and Fisher classes, mainly because I haven't bothered to read them! I presume the many print statements are there for testing and debugging use (good idea ) and you won't use them in the final product.



    The print statements in Lake and FishingRod are only for testing/debugging, I will only use the print statements in Fishing class (well thats the idea!)

    Campbell Ritchie wrote:
    Now, this is the hard bit. Consider what changes you would have to make to the Lake class to make it safe for threaded use. Consider which if its fields will change and which not. If any fields don't change, can you make them final and avoid any threading problems for those fields. If any fields are going to change, how can you make access to them safe for threaded use.



    I'm avoiding adding final to any methods just yet until I get a basic working of the threads sharing the resource (1 lake and 1 rod). Once I have the basic workings, I can go back and put the correct access modifiers on whatever needs it to tighten up the code.

    Campbell Ritchie wrote:

    Bren Reggy wrote:
    . . . My problem is now the threads each instantiate a seperate FishingRod and Lake object (as if they each are fishing in their own lakes!). It is obvious that this is cause the Lake and Rod constructors are in the run() method. I have tried to move this to the main() but the problem is that the run() doesn't recognise "thisLake" object when it's been created in the main(). Probably a silly overlook but how would I resolve this error?


    Ignore it for the time being.



    I solved that initial problem (block scope) and put thisLake and rod1 as class variables. that was a duh moment on my part.

    Campbell Ritchie wrote:
    I presume you have some method of working out which Fisher has a Rod, when he picks up and replaces the Rod, and when it is or is not available for somebody else to take a turn.



    At the moment I'm going to resolve that with an IF statement until I get the shared resource problem worked through. As part of the assignment objective I need to use Synchronised and show possible concurrency errors, but I can't test anything without getting the shared resource problem corrected.


    I have tried putting the new Lake object in the main(), but I get NullPointerExceptions. Tried from outside the main() but each thread still instantiates it's own lake object. So it's trying to work out having 1 object used by three threads is my problem. Can't figure it out.
     
    Campbell Ritchie
    Marshal
    Posts: 79177
    377
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    The lake, rod and fisher fields should be instance fields, not class fields (=static); you should, as a default, not write static. There have been several discussions in the last week about what static means, for example this one, which has links to a classification of when methods might well bestatic.
    You would have a FishingTrip class, which a main method like thisNow you can see you have to initialise the rods, fishers, and lake in the constructor. You can make sure they are not null.

    You will find a link to Effective Java™ (old edition) here; if it works, it explains about the “methods common to all objects”. I think the method you really need here is toString().
     
    Don't get me started about those stupid light bulbs.
    reply
      Bookmark Topic Watch Topic
    • New Topic