gpt4 book ai didi

java - 如何轮流监听两组线程获取synchronized section?

转载 作者:行者123 更新时间:2023-11-30 11:19:19 24 4
gpt4 key购买 nike

我研究 java 中的并发性。最近在学习wait和notify方法的意思。

现在我觉得有时候我应该解决以下问题:

我有

类 ThreadGroup1 扩展线程

class ThreadGroup2 extends Thread

我有每个 Thread 的 300 个实例并同时启动(例如通过 CountDownLatch )

我有同步部分:

synchronized(SharedObjectBetweenThreads){...}

我想获得以下行为:

instance of ThreadGroup1 acquire the section

instance of ThreadGroup2 acquire the section

instance of ThreadGroup1 acquire the section

instance of ThreadGroup2 acquire the section

等等。

我想你明白我想要什么。

我知道,如果我使用等待和通知,我无法保证等待队列中的下一个线程将获取部分。

如何解决所描述的问题?

附言

这个问题与“如何通知具体线程?”的问题有关。

附言

我现在的素描

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++;
}
}

请帮助更正此错误。

根据 hoaz answer 我得到了解决。

请查看此代码:

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;
}
}

最佳答案

您可以找到在这种情况下有用的 ConditionReentrantLock 类:

Lock lock = new ReentrantLock();
Condition threadGroup1 = lock.newCondition();
Condition threadGroup2 = lock.newCondition();
volatile boolean isFirstGroupRunning = true;

将所有四个传递给两个组中的每个线程。您实际上可以将它们组合成新类。在第一个线程组中使用以下代码:

lock.lock();
try {
while (!isFirstGroupRunning) threadGroup2.await();
// do whatever you need to do in first thread
isFirstGroupRunning = false;
threadGroup1.signal();
} finally {
lock.unlock();
}

在第二个线程组做类似的等待/信号序列:

lock.lock();
try {
while (isFirstGroupRunning) threadGroup1.await();
// do whatever you need to do in second thread
isFirstGroupRunning = true;
threadGroup2.signal();
} finally {
lock.unlock();
}

关于java - 如何轮流监听两组线程获取synchronized section?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23300038/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com