I research concurrecy in java. Recently I learn wait and notify methods meaning.
Now I think that sometimes I should to solve following problem:
I have
class ThreadGroup1 extends Thread
and
class ThreadGroup2 extends Thread
I have 300 instances of every Thread and start simultaneously (for example by means of CountDownLatch )
And I have synchronized section:
synchronized(SharedObjectBetweenThreads){...}
I want to get following behaviour:
instance of ThreadGroup1 acquire the section
instance of ThreadGroup2 acquire the section
instance of ThreadGroup1 acquire the section
instance of ThreadGroup2 acquire the section
and so on.
I think you understand what I want.
I know that if I would use wait and notify I cannot guarantee which next thread from waiting queue will acquire section.
How can I solve described issue?
P.S.
This issue relates with question "how to notify concrete thread?"
P.S.
my current sketch
public class ConditionTest {
public static void main(String [] args){
List<Thread> threads = new ArrayList<>();
for(int i=0 ;i<10;i++) {
threads.add(new Thread1());
threads.add(new Thread2());
}
for(Thread thread : threads){
thread.start();
}
}
public static synchronized void method() throws InterruptedException {
System.out.println(Thread.currentThread());
Thread.sleep(500);
}
}
class Thread1 extends Thread{
static int index =0;
int number;
@Override
public void run(){
try {
ConditionTest.method();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
@Override
public String toString(){
return "group1-" + number;
}
Thread1(){
number= index++;
}
}
class Thread2 extends Thread{
static int index =0;
int number;
@Override
public void run(){
try {
ConditionTest.method();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
@Override
public String toString(){
return "group2-" + number;
}
Thread2(){
number= index++;
}
}
please help to correct this.
According hoaz answer I got resolving.
please review this code:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionTest {
static Integer CountThreadInGroup = 10;
public static void main(String[] args) throws InterruptedException {
Lock lock = new ReentrantLock();
boolean isFirstShouldExecute = true;
Condition isFirstExpected = lock.newCondition();
Condition isSecondExpected = lock.newCondition() ;
Synchronizator synchronizator = new Synchronizator(isFirstShouldExecute, lock,isFirstExpected,isSecondExpected);
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < CountThreadInGroup; i++) {
threads.add(new Thread1(synchronizator));
}
for (Thread thread : threads) {
thread.start();
}
threads.clear();
Thread.sleep(100);
for (int i = 0; i < CountThreadInGroup; i++) {
threads.add(new Thread2(synchronizator));
}
for (Thread thread : threads) {
thread.start();
}
}
public static void method() throws InterruptedException {
System.out.println(Thread.currentThread());
Thread.sleep(500);
}
}
class Thread1 extends Thread {
static int index = 0;
int number;
private final Synchronizator synchronizator;
@Override
public void run() {
synchronizator.lock.lock();
try {
while (!synchronizator.isFirstExpected) {
synchronizator.isFirstShouldExecute.await();
System.out.println(Thread.currentThread() + " woke up");
}
ConditionTest.method();
synchronizator.isFirstExpected = false;
synchronizator.isSecondShouldExecute.signal();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} finally {
synchronizator.lock.unlock();
}
}
@Override
public String toString() {
return "\t\t\t group1-" + number;
}
Thread1(Synchronizator synchronizator) {
this.synchronizator = synchronizator;
number = index++;
}
}
class Thread2 extends Thread {
static int index = 0;
int number;
private final Synchronizator synchronizator;
@Override
public void run() {
synchronizator.lock.lock();
try {
while (synchronizator.isFirstExpected) {
synchronizator.isSecondShouldExecute.await();
System.out.println(Thread.currentThread() + " woke up");
}
ConditionTest.method();
synchronizator.isFirstExpected = true;
synchronizator.isFirstShouldExecute.signal();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} finally {
synchronizator.lock.unlock();
}
}
@Override
public String toString() {
return "\t\t\t\t\t\t group2-" + number;
}
Thread2(Synchronizator synchronizator) {
this.synchronizator = synchronizator;
number = index++;
}
}
class Synchronizator{
volatile boolean isFirstExpected ;
Lock lock ;
Condition isFirstShouldExecute;
Condition isSecondShouldExecute;
Synchronizator(boolean isFirstExpected, Lock lock, Condition isFirstShouldExecute, Condition isSecondShouldExecute){
this.isFirstExpected = isFirstExpected;
this.lock =lock;
this.isFirstShouldExecute = isFirstShouldExecute;
this.isSecondShouldExecute = isSecondShouldExecute;
}
}