我正在尝试实现一个模型,其中我有一个主线程,将工作委托给工作线程。这些工作线程在无限循环中运行,定期执行操作,并且在每个操作之后它们正在等待(休眠),直到它们被主线程通知继续。他们还发送一个信息,等待主线程的下一个动作需要多长时间。主线程由最短的等待时间决定,他们在什么时间运行,同时又睡觉。
我已经设计了我认为它可以工作的方式,但是在我运行第一个线程后它会被卡住。我想到的第一件事是糟糕的设计,但我仍然认为这也应该有效。有没有人有建议如何让它工作?非常感谢
编辑:见下面的答案..
答案 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;
}
}