java:实现委托者线程,工作者在无限循环中等待彼此

时间:2015-05-10 16:43:22

标签: java multithreading concurrency executorservice

我正在尝试实现一个模型,其中我有一个主线程,将工作委托给工作线程。这些工作线程在无限循环中运行,定期执行操作,并且在每个操作之后它们正在等待(休眠),直到它们被主线程通知继续。他们还发送一个信息,等待主线程的下一个动作需要多长时间。主线程由最短的等待时间决定,他们在什么时间运行,同时又睡觉。

我已经设计了我认为它可以工作的方式,但是在我运行第一个线程后它会被卡住。我想到的第一件事是糟糕的设计,但我仍然认为这也应该有效。有没有人有建议如何让它工作?非常感谢

编辑:见下面的答案..

1 个答案:

答案 0 :(得分:0)

通过不同的方法,我可以通过这篇文章创建一个有效的解决方案:Using wait/notify vs Thread.sleep() in Java

基本上每个Task(Process1Thread)都从扩展Thread类的父类继承自己的监视器/锁。 Task类中的run()方法在一个无限循环中运行,在一个synchronized块(带有它的监视器/锁)中,并在每个循环结束时通知MainThread而不是等待,将它自己锁定,直到MainThread通知它们继续环。

MainThread将HashMap中的每个任务作为键和时间等待作为值。它还在同步块中的无限循环中运行,其中监视器/锁定用于当前正在运行的任务,从HashMap检查每个循环的最短等待时间,并以最短的等待时间运行任务并等待任务到通知它继续。每次任务在监视器/锁定上发送通知/等待时,MainThread都会继续循环...

无论如何,对于有类似问题的人,请输入以下代码:

AThread课程:

public abstract class AThread extends Thread {
    protected boolean firstRun = true;
    private final Object monitor = new Object();

    protected final Object getMonitor() {
        return monitor;
    }
}

DelegateThread类:

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class DelegateThread {
    public static boolean running = true;
    private static Map<AThread, Integer> map;
    private static Random rand = new Random();

    public static class Process1Thread extends AThread {
        @Override
        public void run() {
            while (running) {
                synchronized (getMonitor()) {
                    try {
                        int time = map.get(this);
                        for (int i = 0; i < time; i++) {
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.print(i + 1 + "-");
                        }
                        System.out.println("Finished task [" + this + "]; Time: " + time);
                        time = randInt(4, 10);
                        System.out.println("new Time for " + this + " is: " + time);
                        map.put(this, time);
                        getMonitor().notify();
                        getMonitor().wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static class Process2Thread extends AThread {... the same as Process1Thread, just different name}

    public static class Process3Thread extends AThread {... the same as Process1Thread, just different name}

    public static class MainThread extends Thread {
        public void run() {
            System.out.println("-= Start =-");
            Map.Entry<AThread, Integer> min;
            while (running) {
                try {
                    min = getMin();
                    synchronized (min.getKey().getMonitor()) {
                        System.out.println("--------------------------------------------------");
                        System.out.println("Sleeping " + min.getKey() + " for: " + min.getValue());
                        Thread.sleep(min.getValue() * 1000);
                        if (min.getKey().firstRun) {
                            min.getKey().start();
                            min.getKey().firstRun = false;
                        }
                        min.getKey().getMonitor().notify();
                        min.getKey().getMonitor().wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(" -= END =- ");
        }

        public Map.Entry<AThread, Integer> getMin() {
            Map.Entry<AThread, Integer> min = null;
            for (Map.Entry<AThread, Integer> entry : map.entrySet()) {
                if (min == null || min.getValue() > entry.getValue()) {
                    min = entry;
                }
            }
            return min;
        }
    }

    public static void main(String[] args) {

        MainThread mainThread = new MainThread();

        Process1Thread process1Thread = new Process1Thread();
        Process2Thread process2Thread = new Process2Thread();
        Process3Thread process3Thread = new Process3Thread();

        map = new HashMap<>(3);
        map.put(process1Thread, 0);
        map.put(process2Thread, 1);
        map.put(process3Thread, 2);

        mainThread.start();
    }

    public static int randInt(int min, int max) {
        return rand.nextInt((max - min) + 1) + min;
    }
}