java - 线程等待多个线程

标签 java multithreading runnable synchronization

我必须创建一个对冲模拟器。有例如。其中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/

相关文章:

java - 多态参数适用于父类(super class),但不适用于子类

Ruby - 多线程 TCP 消息

java - 使用 ThreadPoolExecutor 在同一线程中的 Runnable 实例之间共享数据

java - 停止当前线程,然后创建一个执行相同操作的新线程?

java - 如何将多个对象写入文件?

java - java.util.Date CompareTo 与之前/之后的性能优势?

java - JAX-WS 服务在使用默认构造函数时给出 FileNotFoundException?

C套接字阻塞调用

c++ - 使用 join() 从不同范围运行 C++ 线程

Android 线程和 ArrayAdapter