我有多个资源 - 为了理解说3个资源,即XResource,YResource和ZResource(Java类 - Runnables)能够执行某个任务。有一个任务列表需要在3个资源之间并行完成。我需要锁定资源,如果其中一个资源被锁定,那么任务应该转到其他资源,如果没有资源可用,那么它应该等到其中一个资源可用。我目前正在尝试使用信号量锁定资源,但线程只被分配给一个Runnable而其他Runnables总是空闲。我对多线程很新,所以我可能会忽略一些明显的东西。我正在使用Java SE 1.6
以下是我的代码 -
public class Test {
private final static Semaphore xResourceSphore = new Semaphore(1, true);
private final static Semaphore yResourceSphore = new Semaphore(1, true);
private final static Semaphore zResourceSphore = new Semaphore(1, true);
public static void main(String[] args) {
ArrayList<Task> listOfTasks = new ArrayList<Task>();
Task task1 = new Task();
Task task2 = new Task();
Task task3 = new Task();
Task task4 = new Task();
Task task5 = new Task();
Task task6 = new Task();
Task task7 = new Task();
Task task8 = new Task();
Task task9 = new Task();
listOfTasks.add(task1);
listOfTasks.add(task2);
listOfTasks.add(task3);
listOfTasks.add(task4);
listOfTasks.add(task5);
listOfTasks.add(task6);
listOfTasks.add(task7);
listOfTasks.add(task8);
listOfTasks.add(task9);
//Runnables
XResource xThread = new XResource();
YResource yThread = new YResource();
ZResource zThread = new ZResource();
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < listOfTasks.size(); i++) {
if (xResourceSphore.tryAcquire()) {
try {
xThread.setTask(listOfTasks.get(i));
executorService.execute(xThread );
} finally {
xResourceSphore.release();
}
}else if (yResourceSphore.tryAcquire()) {
try {
yThread.setTask(listOfTasks.get(i));
executorService.execute(yThread );
} finally {
yResourceSphore.release();
}
}else if (zResourceSphore.tryAcquire()) {
try {
zThread.setTask(listOfTasks.get(i));
executorService.execute(zThread );
} finally {
zResourceSphore.release();
}
}
}
executorService.shutdown();
}
}
答案 0 :(得分:1)
您需要将资源锁定逻辑移动到另一个线程中运行的任务。
通过在当前线程中执行锁定,您不会在释放资源之前等待执行任务。您遇到问题的原因是您在同一资源上调用setTask()
之前没有等待任务完成(甚至启动)。这将取代之前的任务集。
Queue<Resource> resources = new ConcurrentLinkedQueue<>();
resources.add(new XResource());
resources.add(new YResource());
resources.add(new ZResource());
ExecutorService service = Executors.newFixedThreadPool(resources.size());
ThreadLocal<Resource> resourceToUse = ThreadLocal.withInitial(() -> resources.remove());
for (int i = 1; i < 9; i++) {
service.execute(() -> {
Task task = new Task();
resourceToUse.setTask(task);
});
}
答案 1 :(得分:0)
根据Peter Lawrey的建议,我在runnable中传递了Semaphore,并在完成执行后将其释放。但是我仍然面临着这样的问题:我无法将所有任务分配给for循环中的线程。所以我做了一个while(true)循环,直到其中一个资源可用于任务。以下是代码:
{{1}}
我不太喜欢这个解决方案,因为如果我的资源正在执行不同类型的任务,它就无法扩展,因此如果我需要特定资源用于特定类型的任务,我的其他任务将持续等待直到特定任务任务完成。但是现在无法通过任何其他方式。即便经过这么多的研究!