Initial Note 1
Instead of manually creating and starting threads, I would suggest using a thread pool that is configured externally so that you can control how many threads are created. If the size of someList is 1000, creating so many threads is inefficient. It is better to use an artist supported by a thread pool. Spring provides some implementations that can be used as Spring beans configured with the task namespace, something like this:
<task:executor id="executor" queue-capacity="10" rejection-policy="CALLER_RUNS" />
queue-capacity - maximum thread pool size. If this size is exceeded, the current thread starts an additional task, thereby blocking the loop until another thread is freed ( rejection-policy="CALLER_RUNS" ). See the task:executor documentation or define any ThreadPoolExecutor (spring or jdk-concurrent) with your own configuration.
Original Note 2
If the only state you are going to store in MyClassImpl is an element from the list, you can forget the rest of the explanation below (except for ThreadPool) and use the singleton bean directly: remove the Runnable interface and its no-arg run() method, add run(OtherClass obj) and follow these steps:
final MyInterface task = // get it from spring as a singleton for (final OtherClass obj : someList) { executor.execute(new Runnable() { public void run() {task.run(obj);} }); // jdk 8 : executor.execute(task::run); }
If you plan to save some state inside MyClassImpl during run() (except for the processed object), continue reading. But you will still use the run(OtherClass obj) method instead of no-args run() .
The main idea is to get a separate object for each working thread based on some model or prototype defined as a Spring bean. To do this, simply define the bean that you initially want to pass to each thread as a proxy server that sends the instance associated with the current thread. This means that the same task instance is injected into each thread, and during the execution of the thread, the real task that you are calling the methods is bound to the current thread.
Main program
Since you use list items for your activities, you will transfer each item to its own task.
public class Program { @Resource private MyInterface task; // this is a proxy @Resource private TaskExecutor executor; public void executeConcurrently(List<OtherClass> someList) { for (final OtherClass obj : someList) { executor.execute(new Runnable() { public void run() { task.run(obj); } }); // jdk 8 : executor.execute(task::run); } } }
Suppose Program is a Spring bean, so dependencies can be introduced. If the Program not a Spring bean, you will need to get W760> ApplicationContext, and then the autowire Program (that is, nest the dependencies found in ApplicationContext based on annotations). Something like this (in the constructor):
public Program(ApplicationContext ctx) { ctx.getAutowireCapableBeanFactory().autowireBean(this); }
Define a task
<bean id="taskTarget" class="MyImplClass" scope="prototype" autowire-candidate="false" /> <bean id="task" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="targetSource"> <bean class="org.springframework.aop.target.ThreadLocalTargetSource"> <property name="targetBeanName" value="taskTarget"/> <property name="targetClass" value="MyInterface"/> </bean> </property> </bean>
taskTarget is where you define your business. This bean is defined as a prototype, since a new instance will be allocated for each thread. Thanks to this, you can even save a state that depends on the run() parameter. This bean is never used directly by the application (thus, autowire-candidate="false" ), but it is used through the task bean. In executeConcurrently() above, the string task.run(obj) will actually be sent to one of the prototypes of the taskTarget that the proxy created.