Announcement Announcement Module
Collapse
No announcement yet.
Threading question Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Threading question

    I have a question about threading.

    I have an application that needs to have the ability to start a number of threads, all doing the same thing with different parameters. These parameters are defined in an external configuration file. I do not know how many threads I will need to start until I read the configuration file that defines this.

    How might I solve this problem with spring? In a Spring-less application, I would simply create an object that implements runnable, pass my Task object to it and start the Thread. Should I do it the same way, or is there a more Spring like way of doing this.

    Thank you for any help you can give.

  • #2
    Sounds like you could use Quartz, which is integrated with Spring.

    http://www.opensymphony.com/quartz/

    Comment


    • #3
      Unless you are moving the config file over to be a spring bean definition file I don't think there is a huge amount of "support" for this in spring. That's not to say that spring can't be helpful - the resource loading, bean utils, and other classes can be used as libraries from your program to keep you from having code similar things. Also, if your Task objects depend on other beans (like a DataSource) you might look into defining a non-singleton bean for the Task, then using the spring beanfactory to return new instances of pre-wired Tasks - your code would still have to set the custom parameters, but you'd remove a lot of the details to the framework.

      Comment


      • #4
        I don't think that Quartz will work for me because I do not want to run these tasks on a schedule, but thanks for the suggestion (it will actaully solve some other issues that I have).

        rrsIPOV, I think I understand what you are saying. Could you see if you think I am on the right track with my thoughts? Thank you.

        What this application does it connect to any number of OPC servers. My first configuration file:

        Code:
        <tasks>
          <task name="task1" running="true" />
          <task name="task2" running="false" />
          <task name="task3" running="true" />
        </tasks>
        After the application reads this file, if the task should be running it will then go and retrieve the //tasks/task@name value and append .xml on it and get the configuration for it.

        Code:
        <!-- task1.xml file -->
        
        <properties>
          <opc host="127.0.0.1" opc-server="MyOPC.Server">
            <item name="Alias1.MYITEM" />
          </opc>
        </properties>
        What I am assuming that I need to do is place a bean in the Spring configuration file that is a non-singleton that implements Runnable and then for each running task in my first config file, retreive that bean, set the properties, from my the second config file, manually and run it. Does this sound like a viable option? Is there a better way of retriving a Runnable bean from the spring config file?

        Comment


        • #5
          I like to control how many threads are running and I like to use the concurrency library from Doug Lea (can be downloaded from his site and is standard in java 5.0).

          I would suggest creating a threadpool that doesn`t do anything but execute runnable`s that are submitted in the threadpool his jobqueue (you can chose from various ExecutorService implementations). You now have total control over the threads...

          So.. after the jobs are submitted in the jobpool you are finished.. but how do you create those jobs? That depends.. I would suggest some kind of 'factory method' that has access to all the parameters that are required. And knows how to create runnable`s to be dropped in the executor service. Here is an example (don`t mind the bugs.)

          Code:
          class JobFactory&#123;
               private String _date;
               private ExecutorService _executorService;
          
               public JobFactory&#40;String data, ExecutorService executorService&#41;&#123;
                   ... set it.
               &#125;
          
               public void fooMethod&#40;&#41;&#123;
                      _executorService.submit&#40;new YourRunnable&#40;&#41;&#41;;
               &#125;
          
                private class YourRunnable implements Runnable&#123;
                    public void run&#40;&#41;&#123;....&#125;
                &#125;
          &#125;
          
          
          <bean id="executorService"
          		class="edu.emory.mathcs.util.concurrent.ThreadPoolExecutor"
          		destroy-method="shutdown">
          
          		<!-- core pool size -->
          		<constructor-arg index="0">
          			<value>5</value>
          		</constructor-arg>
          
          		<!-- max pool size -->
          		<constructor-arg index="1">
          			<value>10</value>
          		</constructor-arg>
          
          		<!-- die-time -->
          		<constructor-arg index="2">
          			<value>5000</value>
          		</constructor-arg>
          
          		<constructor-arg index="3">
          			<ref bean="edu.emory.mathcs.util.concurrent.TimeUnit.MILLISECONDS"/>
          		</constructor-arg>
          
          		<constructor-arg index="4">
          			<bean class="edu.emory.mathcs.util.concurrent.LinkedBlockingQueue">
          				<constructor-arg index="0">
          					<!-- max number of jobs in the queue -->
          					<value>500</value>
          				</constructor-arg>
          			</bean>
          		</constructor-arg>
          	</bean>
          
          	<bean id="jobFactory"
          		class="JobFactory">
          
          		<constructor-arg index="0">
          			<value>your data you care about</value>
          		</constructor-arg>
          
          		<constructor-arg index="1">
          			<ref local="executorService"/>
          		</constructor-arg>
          	</bean>
          The JobFactory was only meant as an example.. the fooMethod could be a method of any object...

          I don`t know how you decide what parameters to use for the threads. But you could add all the parameters to the JobFactory and let him decide how the 'YourRunnables' are going to be parametrised.

          [edit]
          What are your threads going to do anyway? Are your threads running in some kind of loop? (Maybe sleeping if nothing happens) Are they triggered? My solution isn`t very usefull if you need a single dedicated thread doing some kind of job..

          Comment


          • #6
            dfischer - like I said, aside from any framework plumbing (which can be a pretty big part of an application), you may not be able to get too much out of Spring. About the most that you could do is what you wrote, which would at least provide a way to switchout (via the Spring config file) your Runnable bean.

            I am not familiar with OPC, I just looked up the web site and it looks like a pretty large body of work. I don't think Spring provides any more direct support.

            Comment


            • #7
              Thanks to rrsIPOV and Alarmnummer I have been able to get it to work, so far anyway. Thank you both for your input. It has been very helpful.

              Comment


              • #8
                I don't think that Quartz will work for me because I do not want to run these tasks on a schedule
                No probs, but we use Quartz to run some stuff asynchronously, and execute one-off, run-now type jobs. We also use Quartz to avoid reinventing the wheel.

                Using Quartz doesn't mean you have to schedule it to run more than once or at some time in the distant future.

                It sure beats the hell out of faffing about with your own threading, even Doug Lea's great threading library.

                Comment


                • #9
                  gmatthews, could you let me know how you implement this? I would like to try it.

                  Thanks

                  Comment


                  • #10
                    It sure beats the hell out of faffing about with your own threading, even Doug Lea's great threading library.[/quote]
                    The goals of both projects are different. Doug Lea has created a general, easy to use, concurrency library and Quartz is a job scheduling system. So.. it depends on your needs which library to choose.

                    Comment


                    • #11
                      Originally posted by Alarmnummer
                      It sure beats the hell out of faffing about with your own threading, even Doug Lea's great threading library.
                      The goals of both projects are different. Doug Lea has created a general, easy to use, concurrency library and Quartz is a job scheduling system. So.. it depends on your needs which library to choose.

                      Comment


                      • #12
                        So.. it depends on your needs which library to choose
                        Agreed. Always use the simplest thing that works.


                        dfischer, for using Quartz, you'll need one of these

                        Code:
                        <bean name="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
                          <!-- name used to publish applicationContext to Quartz Job instances, so they can call business services -->
                          <property name="applicationContextSchedulerContextKey"><value>applicationContext</value></property>
                        </bean>
                        When you define the property setter for the above, i.e. into a controller that will create new Quartz jobs, you need to define a method that accepts a Scheduler, since that's what the factory returns, e.g. in my controller

                        Code:
                        <property name="scheduler"><ref bean="schedulerFactory"/></property>
                        You'll also need some client code to launch the job something like this.

                        Code:
                        ... if some button clicked then ...
                        JobDetail jobDetail = new JobDetail&#40;jobName, jobGroup, MyQuartzJob.class&#41;;
                        jobDetail.getJobDataMap&#40;&#41;.put&#40;"myParam", myValue&#41;;
                        
                        Trigger trigger = new SimpleTrigger&#40;myTriggerName, jobGroup, 0, 0&#41;;
                        scheduler.scheduleJob&#40;jobDetail, trigger&#41;;
                        where MyQuartzJob starts out something like this.

                        Code:
                        public void execute&#40;JobExecutionContext jec&#41; throws JobExecutionException &#123;
                        
                          JobDataMap jobDataMap = jec.getJobDetail&#40;&#41;.getJobDataMap&#40;&#41;;
                          try &#123;
                            SchedulerContext schedulerContext = jec.getScheduler&#40;&#41;.getContext&#40;&#41;;
                            ApplicationContext applicationContext = &#40;ApplicationContext&#41; schedulerContext.get&#40;"applicationContext"&#41;;
                        ... and so on. At this point, you're executing in a thread created by Quartz.

                        You can also take advantage of other Quartz capabilities like advanced scheduling ala cron, and the ability to persist jobs easily in a db so you can scale + handle crashes.

                        Comment


                        • #13
                          grr.. stupid browser.. I wanted to do an edit..

                          Comment


                          • #14
                            Thank you very much to everyone that responded. I have implemented Quartz and it is working like a charm. I do agree that there is a place for both of these libraries, but the simplest solution was Quartz. Thanks again.

                            Comment

                            Working...
                            X