/**
* ZKLockConcurrentTest.java
*
* Copyright 2016 the original author or authors.
*
* We licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.apache.niolex.lock;
import static org.junit.Assert.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.niolex.commons.test.MockUtil;
import org.apache.niolex.notify.AppTest;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author <a href="mailto:xiejiyun@foxmail.com">Xie, Jiyun</a>
* @version 1.0.0
* @since 2016-4-15
*/
public class ZKLockConcurrentTest {
private static final String BS = "/lock/zkc/tmp-" + MockUtil.randInt(100, 999);
private static int THREAD_CNT = 10;
private static int TOTAL_CNT = 100;
@Test
public void testConcLock() throws Exception {
THREAD_CNT = 4;
TOTAL_CNT = 50;
main(null);
}
public static void main(String[] args) throws Exception {
AppTest.cleanZK(BS);
Thread[] tarr = new Thread[THREAD_CNT];
final AtomicInteger count1 = new AtomicInteger();
final AtomicInteger count2 = new AtomicInteger();
final AtomicInteger flag = new AtomicInteger();
for (int i = 0; i < THREAD_CNT; ++i) {
ZKLock lock = new ZKLock(AppTest.URL, 6000, BS);
if (i % 2 == 0) {
tarr[i] = new Thread(new ZKLockConcurrent1(lock, count1, flag, TOTAL_CNT));
} else {
tarr[i] = new Thread(new ZKLockConcurrent2(lock, count2, flag, TOTAL_CNT));
}
tarr[i].start();
}
for (int i = 0; i < THREAD_CNT; ++i) {
tarr[i].join();
}
assertEquals(TOTAL_CNT * THREAD_CNT / 2, count1.get());
assertTrue(count2.get() <= count1.get());
assertEquals(0, flag.get());
System.out.println("testConcLock done.");
}
}
class ZKLockConcurrent1 implements Runnable {
protected static final Logger LOG = LoggerFactory.getLogger(ZKLockConcurrentTest.class);
private final ZKLock lock;
private final AtomicInteger count;
private final AtomicInteger flag;
private final int totalCount;
/**
* Constructor
* @param lock
* @param count
* @param flag
* @param totalCount
*/
public ZKLockConcurrent1(ZKLock lock, AtomicInteger count, AtomicInteger flag, int totalCount) {
super();
this.lock = lock;
this.count = count;
this.flag = flag;
this.totalCount = totalCount;
}
/**
* This is the override of super method.
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
for (int i = 0; i < totalCount; ++i) {
lock.lock();
try {
int c = flag.incrementAndGet();
count.incrementAndGet();
if (c != 1) {
LOG.error("Failed to keep lock semantics: c = " + c);
}
flag.decrementAndGet();
} finally {
lock.unlock();
}
}
LOG.error("ZKLockConcurrent1 finished.");
}
}
class ZKLockConcurrent2 implements Runnable {
protected static final Logger LOG = LoggerFactory.getLogger(ZKLockConcurrentTest.class);
private final ZKLock lock;
private final AtomicInteger count;
private final AtomicInteger flag;
private final int totalCount;
/**
* Constructor
* @param lock
* @param count
* @param flag
* @param totalCount
*/
public ZKLockConcurrent2(ZKLock lock, AtomicInteger count, AtomicInteger flag, int totalCount) {
super();
this.lock = lock;
this.count = count;
this.flag = flag;
this.totalCount = totalCount;
}
/**
* This is the override of super method.
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
for (int i = 0; i < totalCount; ++i) {
try {
if (lock.tryLock(100, TimeUnit.MILLISECONDS))
try {
int c = flag.incrementAndGet();
count.incrementAndGet();
if (c != 1) {
LOG.error("Failed to keep lock semantics: c = " + c);
}
flag.decrementAndGet();
} finally {
lock.unlock();
}
} catch (InterruptedException e) {
}
}
LOG.error("ZKLockConcurrent2 finished.");
}
}