I am trying to add ReentrantLock
in my work on SpringXD, but it sometimes seems there are interruptions across threads.
For example, I have these code:
public class LoadGenerator extends MessageProducerSupport {
private final AtomicBoolean running = new AtomicBoolean(false);
private ExecutorService executorService;
Logger logger = LoggerFactory.getLogger(LoadGenerator.class);
public LoadGenerator(){}
@Override
protected void doStart() {
executorService = Executors.newFixedThreadPool(2);
if (running.compareAndSet(false, true)) {
for (int x = 0; x < 10; x++) {
executorService.submit(new Producer(Integer.toString(x)));
}
}
}
@Override
protected void doStop() {
if (running.compareAndSet(true, false)) {
executorService.shutdown();
}
}
protected class Producer implements Runnable {
String prefix;
Lock lock = new ReentrantLock();
public Producer(String prefix) {
this.prefix = prefix;
}
private void send() {
lock.lock();
try{
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " " + i);
}
}finally{
lock.unlock();
}
}
public void run() {
send();
}
}
}
what I expected from it, is a list like
pool-604-thread-1 0
pool-604-thread-1 1
pool-604-thread-1 2
pool-604-thread-1 3
pool-604-thread-1 4
pool-604-thread-1 5
pool-604-thread-1 6
pool-604-thread-1 7
pool-604-thread-1 8
pool-604-thread-1 9
pool-604-thread-2 0
pool-604-thread-2 1
pool-604-thread-2 2
pool-604-thread-2 3
pool-604-thread-2 4
pool-604-thread-2 5
pool-604-thread-2 6
pool-604-thread-2 7
pool-604-thread-2 8
pool-604-thread-2 9
...
The sequence and order in every thread should not be interrupted, but the fact is there are sometimes interruption like:
pool-604-thread-1 0
pool-604-thread-2 0
pool-604-thread-2 1
pool-604-thread-2 2
pool-604-thread-1 1
pool-604-thread-1 2
pool-604-thread-1 3
What is wrong? the lock is working good in localhost on Eclipse, tested.
Is it because SpringXD is distributed system? But I only have one xdcontaier connected to my xdadmin.
Thanks.
You should pass your ReentrantLock
not create it in every new Runnable
, the Producers should share one ReentrantLock
, like:
@Override
protected void doStart() {
executorService = Executors.newFixedThreadPool(2);
Lock lock = new ReentrantLock(); // create a share lock to lock in multi threads
if (running.compareAndSet(false, true)) {
for (int x = 0; x < 10; x++) {
executorService.submit(new Producer(Integer.toString(x), lock)); //pass this lock to every producer
}
}
}
protected class Producer implements Runnable {
String prefix;
final Lock lock;
public Producer(String prefix, Lock lock) {
this.prefix = prefix;
this.lock = lock;
}
private void send() {
lock.lock();
try{
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " " + i);
}
}finally{
lock.unlock();
}
}
public void run() {
send();
}
}