我必须创建一个对冲模拟器。有例如。其中10个Segment,每个Segment都应该有自己的专用线程来模拟Segment的增长(每次我们要计算Segment是否增长时,我们应该进行随机测试)。 此外,还应该有一个额外的园丁线程。 当 Gardener 的大小达到 10 时,Garden 应该将其切掉(然后他将其大小切回到初始水平 1 并在笔记中添加通知)。
我尝试让它工作是这样的:
public class Segment implements Runnable {
private int currentSize;
@Override
public void run() {
if(Math.random() < 0.3)
incrementSize();
}
private synchronized void incrementSize() {
currentSize++;
}
public synchronized int getCurrentSize() {
return currentSize;
}
public synchronized void setCurrentSize(int newSize) {
currentSize = newSize;
}
}
public class Gardener implements Runnable {
private int[] segmentsCutAmount = new int[10]; //Gardener notes
private Collection<Segment> segments;
public Gardener(Collection<Segment> segmentsToLookAfter) {
segments = segmentsToLookAfter;
}
@Override
public void run() {
while(true) {
//Have no idea how to deal with 10 different segments here
}
}
}
public class Main {
private Collection<Segment> segments = new ArrayList<>():
public void main(String[] args) {
Main program = new Main();
for(int i = 0; i < 10; i++)
program.addSegment();
Thread gardenerThread = new Thread(new Gardener(program.segments));
}
private void addSegment(Collection<Segment> segments) {
Segment segment = new Segment();
Thread segmentThread = new Thread(segment);
segmentThread.start();
segments.add(segment);
}
}
当段达到最大高度时,我不确定我应该做什么。 如果有10个园丁,每个人都可以观察一个片段,但不幸的是,园丁是一个孤独的射手——他没有家人,他的 friend 都很忙,不愿意帮助他。你愿意帮助我吗? :D 我通常知道同步的基础知识 - 同步方法/ block 、锁、等待和通知方法,但这次我完全不知道该怎么做:( 这就像可怕的僵局!当然,我不希望被喂食。任何类型的提示也会非常有帮助。预先感谢您,祝您有美好的一天!
最佳答案
关于那个队列。您可以使用 ExecutorService
为此。
让树篱生长
所以让你拥有一个可以生长和修剪的树篱。
class Hedge {
private AtomicInteger height = new AtomicInteger(1);
public int grow() {
return height.incrementAndGet();
}
public int cut() {
return height.decrementAndGet();
}
}
然后你就有了一个可以让树篱生长的环境。这将模拟树篱部分;每个环境仅负责其中一个部分。它还会通知 Consumer<Integer>
当树篱尺寸消失时。
class SectionGrower implements Runnable {
public static final Random RANDOM = new Random();
private final Hedge hedge;
private final Consumer<Integer> hedgeSizeListener;
public SectionGrower (Hedge h, Consumer<Integer> hl) {
hedge = h;
hedgeSizeListener = hl
}
public void run() {
while (true) { // grow forever
try {
// growing the hedge takes up to 20 seconds
Thread.sleep(RANDOM.nextInt(20)*1000);
int sectionHeight = hedge.grow();
hedgeSizeListener.accept(sectionHeight);
} catch (Exception e) {} // do something here
}
}
}
所以此时,您可以这样做。
ExecutorService growingExecutor = Executors.newFixedThreadPool(10);
Consumer<Integer> printer = i -> System.out.printf("hedge section has grown to %d\n", i.intValue());
for (int i = 0; i < 10; i++) {
Hedge section = new Hedge();
Environment grower = new SectionGrower(section, printer);
growingExecutor.submit(grower::run);
}
这将生长 10 个树篱部分,并在生长时打印每个树篱部分的当前高度。
添加园丁
所以现在你需要一个可以修剪树篱的园丁。
class Gardener {
public static final Random RANDOM = new Random();
public void cutHedge(Hedge h) {
try {
// cutting the hedge takes up to 10 seconds
Thread.sleep(RANDOM.nextInt(10)*1000);
h.cut();
} catch (Exception e) {} // do something here
}
}
现在你需要一些构造来给他工作;这就是BlockingQueue
的地方我们已经确定 Environment
可以通知Consumer<Integer>
当一个部分增长之后,这就是我们可以使用的。
ExecutorService growingExecutor = Executors.newFixedThreadPool(10);
// so this is the queue
ExecutorService gardenerExecutor = Executors.newSingleThreadPool();
Gardener gardener = new Gardener();
for (int i = 0; i < 10; i++) {
Hedge section = new Hedge();
Consumer<Integer> cutSectionIfNeeded = i -> {
if (i > 8) { // size exceeded?
// have the gardener cut the section, ie adding item to queue
gardenerExecutor.submit(() -> gardener.cutHedge(section));
}
};
SectionGrower grower = new SectionGrower(section, cutSectionIfNeeded);
growingExecutor.submit(grower::run);
}
所以我还没有真正尝试过这个,但它应该可以通过一些小的调整来工作。
请注意,我使用 AtomicInteger
在树篱中,因为它可能会“同时”生长和被切割,因为这发生在不同的线程中。
关于java - 线程等待多个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50197525/