Announcement Announcement Module
Collapse
No announcement yet.
Concurrancy, ThreadPools, and Message Queues Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Concurrancy, ThreadPools, and Message Queues

    I would like some feedback on a business problem and some proposed solutions.

    My app, running under JBoss, will be receieing a 'Job' request on a JMS queue.

    I need to be able to support 3 jobs running simultaneous. Each job will have 1-6 files, which I would also like to process concurrent, up to 3 at a time. Finally, each file will have multiple patients, which I would like to process 3 at a time.

    My first thought was 3 levels of TaskExecutors using thread pooling. The JobExecutor could draw from a pool of 3 threads, each JobExecutor could spawn a FileExecutor, which would have a separate pool of 3 threads, and each FileExecutor would spawn a PatientExecutor, with a separate pool of 3 threads.

    Then I realized that if I have 3 JobExecutors running, they are each drawing from the SAME pool of FileExecutors - same with File to Patient. So instead of ending up with 3*3*3 = 27 threads processing, I would only have 3+3+3 = 9 threads processing.

    I also discovered the Concurrency Interceptor, which made me question using threads at all IF I can make the three layers Singletons.

    My peers wish to use MDB's (EJB's) since we are in a JBoss environment, and leverage JMS queues as 'pools' that the MDB's would draw from. This would give the added ability of persistance in the queues, which may have value, but only at the top 2 layers.

    I am leaning back towards my first solution, but doe sthat mean TaskExecutors as prototype beans, with Thread pools being created as needed instead of being 'ready to go'? Is there a cleaner solution, or best practice in this area that I am missing?

    Any discussion is appreciated.

    Ed

  • #2
    Create 3 Executors that are singleton:

    Code:
    <bean id="jobExecutor" class="ThreadPoolExecutor">
        <property name="corePoolSize" value="3"/>
    </bean>
    
    <bean id="fileExecutor" class="ThreadPoolExecutor">
        <property name="corePoolSize" value="3"/>
    </bean>
    
    <bean id="patientExecutor" class="ThreadPoolExecutor">
        <property name="corePoolSize" value="3"/>
    </bean>
    And you can inject these beans in all objects that require them. Now you have 9 threads running (3+3+3).

    If the tasks for the jobexecutor need to access to the fileExecutor, you can do the following:

    Code:
    public class JobRunnableGenerator{
       
       private FileRunnableGenerator fileRunnableGenerator;
       private Executor fileRunnableExecutor;
    
       public Runnable generate(Job job){
           return new JobRunnable(job);
       }
    
       private class JobRunnable implements RUnnable{
           private Job job;
           JobRunnable(Job job){
                this.job = job;
           }
    
           public void run(){
                 ...do some job calculations.
                 for(File file: job.getFiles()){
                      FileRunnable fileRunnable = fileRunnableGenerator.generate(file);
                      fileRunnableExecutor.execute(fileRunnable);  
                 }
           }
       }
    }
    
    <bean id="jobRunnableGenerator" class="JobRunnableGenerator">
         <property name="fileRunnableGenerator" ref="fileRunnableGenerator"/>
         <property name="fileRunnableExecutor" ref="fileRunnableExecutor"/>
    </bean>
    And for the fileRunnableGenerator you can do the same.

    Personally I prefer to create my executors up front and not on the fly when I need them. I want to have complete control on the number of threads running... but I also want to have complete control on the lifecycle of the executors. That is why I also connect the shutdown methods of the executor to the shutdown method of the bean (so if the container is destroyed, the executors are destroyed also).

    Btw:
    This is only a direct answer to your question. This is not an answer if MDB is a better approach than this one... So it could be that MDB`s are a better solution (or not )
    Last edited by Alarmnummer; May 23rd, 2006, 07:36 AM.

    Comment


    • #3
      Originally posted by Alarmnummer
      Create 3 Executors that are singleton:

      And you can inject these beans in all objects that require them. Now you have 9 threads running (3+3+3).

      Personally I prefer to create my executors up front and not on the fly when I need them. I want to have complete control on the number of threads running... but I also want to have complete control on the lifecycle of the executors. That is why I also connect the shutdown methods of the executor to the shutdown method of the bean (so if the container is destroyed, the executors are destroyed also).
      I also prefer to build my executors up front.

      The above was my first thought, but I don't want 3+3+3, I want 3*3*3.

      Comment


      • #4
        Originally posted by ed4becky
        I also prefer to build my executors up front.

        The above was my first thought, but I don't want 3+3+3, I want 3*3*3.
        I think you want 3+3*3+3*3*3=39.

        But do the executors need to be independant?

        Comment


        • #5
          Originally posted by Alarmnummer
          I think you want 3+3*3+3*3*3=39.

          But do the executors need to be independant?
          Only in that if I have 1 JobExecutor running, I want it to be able to spawn up to 3 file processors, but I don't want it to use 8 FileExecutors and there not be 3 left for another JobExecutor if it gets called..

          Comment


          • #6
            This is not what I meant. THe executors for Job don't interfere with those of the FileExecutor.. and also not with the Executors for the patients.

            What I meant was: do you need 3 executors for Job? (with 3 threads each) or is a single executor with a couple of threads(could be nine) be just as good?

            This would be my prefered choice.. I don't see any good reasons unless you have some serious realtime issues.

            Comment


            • #7
              I wasn't worried about JobExecutor using the FileExecutor's pool, just the first JobExecutor using more than it's fair share of FileEexcutors

              Originally posted by Alarmnummer
              What I meant was: do you need 3 executors for Job? (with 3 threads each) or is a single executor with a couple of threads(could be nine) be just as good?
              The jobs can be long running (20 minutes to 2 hrs) and the JobExecutor needs to maintain state until it is complete. I could store the state, but I need to limit the number of jobs running concurrently as well.

              Comment


              • #8
                Originally posted by ed4becky
                The jobs can be long running (20 minutes to 2 hrs) and the JobExecutor needs to maintain state until it is complete. I could store the state, but I need to limit the number of jobs running concurrently as well.
                Why does it need to maintain state? And you can create runnable`s that contain all state. So why does you JobExecutor needs to maintain state? And I don't see what maintaing state has to do with the maximum number of concurrent jobs.

                Comment


                • #9
                  Originally posted by ed4becky
                  The jobs can be long running (20 minutes to 2 hrs) and the JobExecutor needs to maintain state until it is complete. I could store the state, but I need to limit the number of jobs running concurrently as well.
                  Does a JobExecutor/FileExecutor have anything else to do except for breaking a job/file into files/patients and hand each file/patient over to a lower level executor and then just wait?

                  Comment


                  • #10
                    Maybe you can have a look at:

                    http://incubator.apache.org/servicemix/beanflow.html

                    Comment


                    • #11
                      Originally posted by manifoldronin
                      Does a JobExecutor/FileExecutor have anything else to do except for breaking a job/file into files/patients and hand each file/patient over to a lower level executor and then just wait?
                      I'm not explaining this well, let me try again.

                      My intent in JobExecutor is fourfold:
                      - a way of throttling so that only three jobs can run at a time.
                      - collects data shared by processing of all files
                      - divides the job into files, and executes a FileExecutor for each
                      - after all files are complete, captures that the job is complete
                      then it returns to pool so another job can run.

                      A my intent for FileExecutor is similiar:
                      - a way of throttling so that each JobExecutor can process files concurrently, but only up to some limit per JobExecutor
                      - collects data shared by processing of all patients
                      - divides the file into patients
                      - after all patients are complete, captures status of file
                      then it returns to pool so that the parent JobExecutor can process another file.

                      PatientExecutor is simple - allow the FileExecutor to process x number of patients concurrently. Each FileExecutor is limited to a certain number form the pool.

                      That is what I am after anyway...

                      Comment


                      • #12
                        So in other words, a JobExecutor/FileExecutor doesn't really have anything else to do except for waiting while every patient is being processed. I don't really see any reason to have them running in separate threads. The status of a job, including a quota that caps the number of concurrent patients being processed, can be kept in a non-thread data structure. You only need one global "dispatcher" thread to scan through a list of these jobs, and take action according to each one's current status. E.g., if a job current has a patient that's waiting to be processed, and this job still has some quota left, spawn a new PatientExecutor.

                        Comment

                        Working...
                        X