/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed 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 com.hazelcast.concurrent.lock; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.core.ICondition; import com.hazelcast.core.ILock; import com.hazelcast.test.HazelcastParallelClassRunner; import com.hazelcast.test.HazelcastTestSupport; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.assertNull; @RunWith(HazelcastParallelClassRunner.class) public class ProducerConsumerConditionStressTest extends HazelcastTestSupport { private static volatile Object object; public static final int ITERATIONS = 1000000; public static final int PRODUCER_COUNT = 2; public static final int CONSUMER_COUNT = 2; public static final int INSTANCE_COUNT = 1; @Test public void test() { HazelcastInstance[] instances = createHazelcastInstanceFactory(INSTANCE_COUNT).newInstances(); HazelcastInstance hz = instances[0]; ILock lock = hz.getLock(randomString()); ICondition condition = lock.newCondition(randomString()); ConsumerThread[] consumers = new ConsumerThread[CONSUMER_COUNT]; for (int k = 0; k < consumers.length; k++) { ConsumerThread thread = new ConsumerThread(k, lock, condition); thread.start(); consumers[k] = thread; } ProducerThread[] producers = new ProducerThread[PRODUCER_COUNT]; for (int k = 0; k < producers.length; k++) { ProducerThread thread = new ProducerThread(k, lock, condition); thread.start(); producers[k] = thread; } assertJoinable(600, producers); assertJoinable(600, consumers); for (TestThread consumer : consumers) { assertNull(consumer.throwable); } for (TestThread producer : producers) { assertNull(producer.throwable); } } abstract class TestThread extends Thread { private volatile Throwable throwable; TestThread(String name) { super(name); } public void run() { try { for (int k = 0; k < ITERATIONS; k++) { runSingleIteration(); if (k % 100 == 0) { System.out.println(getName() + " is at: " + k); } } } catch (Throwable e) { this.throwable = e; e.printStackTrace(); } } abstract void runSingleIteration() throws InterruptedException; } class ProducerThread extends TestThread { private final ILock lock; private final ICondition condition; ProducerThread(int id, ILock lock, ICondition condition) { super("ProducerThread-" + id); this.lock = lock; this.condition = condition; } void runSingleIteration() throws InterruptedException { lock.lock(); try { while (object != null) { condition.await(); } object = ""; condition.signalAll(); } finally { lock.unlock(); } } } class ConsumerThread extends TestThread { private final ILock lock; private final ICondition condition; ConsumerThread(int id, ILock lock, ICondition condition) { super("ConsumerThread-" + id); this.lock = lock; this.condition = condition; } void runSingleIteration() throws InterruptedException { lock.lock(); try { while (object == null) { condition.await(); } object = null; condition.signalAll(); } finally { lock.unlock(); } } } }