I know that question about reusing prototype beans was asked many times, but my question means more than this.
What is the problem:
I start asynchronous tasks in handler (prototype bean) in for-lookup. but I can't start the next asynchronous task before the previous reach some milestone. So I have to proceed for-loop only after the previous task invokes a special method.
What the questions:
@Service(value = "Request.Start")
@Scope("prototype")
public static class Start {
public Start() {}
private Object lock;
@Transactional
public void handler(Request request, Response response) {
for (int i = 0; i < request.getAmount(); i++) {
Utils.asyncProcessStart(); //Can't start the next async process before the previous rich some defined milestone
lock.wait();
}
}
public void proceedLookUp() {
lock.notify();
}
}
@Service
public void AsynchronousTask {
public void asyncAction() [
//Needed logic, before start the next async task
getStartHandler().proceedLookUp();
}
public void getStartHandler() {
//HOW TO REWRITE NEEDED PROTOTYPE BEAN
}
}
ADDITION:
What is the problem: I use Activiti framework, which imply some restrictions. I should store some variables to a process (thread) context. I CAN write variables to a global context, BUT CAN'T write to a local process (thread) context before the process (thread) has been started.
what you expect to happen, say if request.getAmount() returns 2?
I should start two asynchronous processes in two different threads. Each process have the same set of variables. I must write appropriate variables to the local context of each process (thread). But, I CAN'T do it before the process (thread) is started (due to the specific of Activiti framework).
For example, each process (thread) should write "id" property to his own local context. I have List ids in handler method
So, I should do the next sequence of actions:
Why can't you just call it synchronously?
As you have already understood, there is no guarantee that the first process (thread) write the "id"-property to it local context, before it has been overriden by for-loop for the second process (thread).
Here's my suggestion: create a singleton object that you can share between your threads to pass information (state). The singleton uses a semaphore to coordinate between your threads. You can use this approach to pass the new thread's identity back to your Service class. Here's a simple example that shows what I'm proposing.
The test class:
public class TestSemaphore {
@Test
public void test() throws Exception {
ThreadCoordinator tc = ThreadCoordinator.getInstance();
for( int i = 0; i < 100; i++ ) {
MyThread r = new MyThread();
r.run();
// This will block until the Thread has called release (after setting its identity on the ThreadCoordinator)
tc.acquire();
String newThreadIdentity = tc.getIdentity();
System.out.println( "Received the new thread's identity: " + newThreadIdentity );
// This will allow the next Thread to acquire the semaphore
tc.release();
}
}
class MyThread extends Thread {
public void run() {
String identity = Integer.toString( (int)(Math.random() * 10000) );
System.out.println( "Running a new thread with identity: " + identity );
// Get a reference to the singleton
ThreadCoordinator tc = ThreadCoordinator.getInstance();
try {
tc.acquire();
tc.setIdentity( identity );
System.out.println( "Notified the ThreadCoordinator from thread: " + identity );
tc.release();
} catch( InterruptedException e ) {
System.out.println( "Caught an interrupted exception: " + e );
}
}
}
}
The ThreadCoordinator (semaphore) class:
import java.util.concurrent.Semaphore;
public class ThreadCoordinator {
private static ThreadCoordinator tc = new ThreadCoordinator();
private static Semaphore semaphore = new Semaphore( 1, true );
private static String identity;
// singleton get instance
public static ThreadCoordinator getInstance() {
return ThreadCoordinator.tc;
}
public void setIdentity( String identity ) throws InterruptedException {
ThreadCoordinator.identity = identity;
}
public String getIdentity() throws InterruptedException {
String identity = ThreadCoordinator.identity;
ThreadCoordinator.identity = null;
return identity;
}
public void acquire() throws InterruptedException {
ThreadCoordinator.semaphore.acquire();
}
public void release() {
ThreadCoordinator.semaphore.release();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With