• Post Reply Bookmark Topic Watch Topic
  • New Topic

New Runnable vs New (Class-Extending-Thread) as a parameter in Thread t = new Thread(/*Over here*/)

 
Harshil Mavani
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


The initateBatch Method Spawns two Threads. And my doubt lies here. If i use Thread t1 = new Thread(new Runnabble(){ and over ride the run here, }) for both threads, i get my job completed in 4000 mill secs
If i use Thread t2 = new Thread(new Worker(){}) for both threads my job completes in 2000 millisecs with Exception thrown at times
I am new to the ranch.Thank you.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Likes 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In my opinion, you should never extend Thread. There is very (very very very) little reason to, but there are consequences and side effects. Most of the time you are just using it as a Runnable (as in this case) or to override the run() method, which is essentially what providing a Runnable does anyway. So you are better off implementing Runnable.

But in your case, the problem isn't about Thread versus Runnable. It is the fact that when you create a new Worker, you are creating a new instance and calling that new instance's work methods. Each new instance has its own locks, and so the two threads don't synchronize with each other. Since you made your lists static, all instances share the same list, even though they aren't synchronized, so you get a situation where you are modifying the same data in two different threads at the same time. This concurrent modification interferes with operations and you. get errors.

My standard approach would be to lock on the data that is being modified. So I would make the two doWork... methods like this:

That would fix the problem. I also think that you are doing too much with Worker - it is confusing because you have an instance which would be used to create the Threads and kick off the work, but doesn't do any work. Then two other instances which aren't used to kick off threads but actually do the work. I think you could fix the problem by making initiateBatch static. I think that would at least make it clear that you don't need an instance to start the work. You might also consider moving the initializeBatch method to a different class - perhaps a Batch class which also maintains the lists. But that is an idea for later on.

Finally, I don't think the work is doing what you expect. The first thread will fill both lists to 2000. The second thread needs to wait for the first thread to complete working on the first list before it can start. So by the time it starts the list is already at 2000 entries and the second thread has no work to do so it waits for the second list to become available. The second list becomes available after the first thread fills it to 2000 and then the second thread can work on it. But it, too, is already filled so the second thread has nothing to do and comes to an immediate close. To show this, time the code as it is currently written, and then comment out lines 45 and 46 so the second thread has no work to do, and time it again. You will see no difference in time because the second thread doesn't do anything.
 
Ulf Dittmer
Rancher
Posts: 42970
73
 
Harshil Mavani
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you very much Steve. It has helped me a lot.
 
Harshil Mavani
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
just one question...is there anyway that i can have two synchronized blocks with different locks BUT can i have two separate threads working on each block? For Eg. After your reply i decided to do this
------------------------------------------------------------------------CODE----------------------------------------------------------


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
But just as you suggested... The Thread one is only doing all the work..the thread two has nothing to do.
i want it work in a way where, when thread one has a lock on the job_list_1, i want thread two to proceed with job_list_2 block...is that possible or am i big big noob :P
Really sorry if i am annoying.
Thank you
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It is possible, but you have to be clear about exactly what you need. In your current scenario you have two stages of the work. Stage one is handled by doWorkStage1() and works on job_list_1, and stage 2 is handled by doWorkStage2() and works on job_list_2. In the current setup, it appears like you must do stage 1 before you do stage 2 for some reason. Now, the code you posted doesn't have any dependency but if you are modeling a real-life scenario, that dependency might actually exist. If there is no such dependency then I would make it so the first thread's Runnable only calls doWorkStage1() and the second thread's Runnable only calls doWorkStage2().

But if there is a requirement that the first stage be complete before you do the second stage, then you need to work a bit harder. If you need the results of stage 1 in order to do the work in stage 2, but you don't need all the results at once, then perhaps you can use a Queue to feed results into the second stage as they are completed. So thread 1 can be doing stage 1 and feeding results to stage 2, and thread 2 can concurrently be working on stage 2, taking results from stage 1, and working at least one result behind, but maybe more.

There are other scenarios that allow more or less overlap, so you need to define the parameters first before you can design a solution.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!