Java 多线程:分配和阻塞资源的问题
我有多种资源——为了理解,比如说3种资源,即XResource、YResource和ZResource(Java类-Runnables),它们能够完成特定的任务。在这三种资源中有一个需要并行完成的任务列表。我需要锁定资源,如果其中一个资源被锁定,那么任务应该转到其他资源,如果没有任何资源可用,那么它应该等到其中一个资源可用。我目前正在尝试使用信号量获取资源的锁,但是线程只被分配给一个可运行线程,而其他可运行线程总是空闲的。我对多线程非常陌生,所以我可能忽略了一些显而易见的东西。我正在使用JavaSE1.6 下面是我的代码-Java 多线程:分配和阻塞资源的问题,java,multithreading,Java,Multithreading,我有多种资源——为了理解,比如说3种资源,即XResource、YResource和ZResource(Java类-Runnables),它们能够完成特定的任务。在这三种资源中有一个需要并行完成的任务列表。我需要锁定资源,如果其中一个资源被锁定,那么任务应该转到其他资源,如果没有任何资源可用,那么它应该等到其中一个资源可用。我目前正在尝试使用信号量获取资源的锁,但是线程只被分配给一个可运行线程,而其他可运行线程总是空闲的。我对多线程非常陌生,所以我可能忽略了一些显而易见的东西。我正在使用Java
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();
}
}
公共类测试{
私有最终静态信号量xResourcesHole=新信号量(1,true);
私有最终静态信号量yResourceSphore=新信号量(1,true);
私有最终静态信号量zResourceSphore=新信号量(1,true);
公共静态void main(字符串[]args){
ArrayList listOfTasks=新建ArrayList();
任务task1=新任务();
任务task2=新任务();
任务task3=新任务();
任务task4=新任务();
任务task5=新任务();
任务task6=新任务();
任务task7=新任务();
Task task8=新任务();
任务task9=新任务();
添加(任务1);
添加(任务2);
添加(任务3);
添加(任务4);
添加(任务5);
添加(任务6);
添加(任务7);
添加(任务8);
添加(任务9);
//可运行
XResource xThread=新的XResource();
YResource yThread=新的YResource();
ZResource zThread=新ZResource();
ExecutorService ExecutorService=Executors.newFixedThreadPool(3);
for(int i=0;i
您需要将资源锁定逻辑移动到在另一个线程中运行的任务
通过在当前线程中执行锁定,您不会等待在释放资源之前执行任务。您看到问题的原因是,在对同一资源调用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);
});
}
队列资源=新的ConcurrentLinkedQueue();
添加(新的XResource());
添加(新的YResource());
添加(新的ZResource());
ExecutorService=Executors.newFixedThreadPool(resources.size());
ThreadLocal resourceToUse=ThreadLocal.withInitial(()->resources.remove());
对于(int i=1;i<9;i++){
service.execute(()->{
任务=新任务();
resourceToUse.setTask(任务);
});
}
根据Peter Lawrey的建议,我在runnable中传递了信号量,并在完成执行后将其释放。但是,我仍然面临一个问题,即我无法将所有任务分配给for循环中的线程。所以我做了一个while(true)循环,直到其中一个资源可用于某个任务。代码如下:
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < listOfTasks.size(); i++) {
while(true){
if (xResourceSphore.tryAcquire()) {
xThread.setTask(listOfTasks.get(i));
xThread.setSemaphore(xResourceSphore);
executorService.execute(xThread );
break;
}else if (yResourceSphore.tryAcquire()) {
yThread.setTask(listOfTasks.get(i));
yThread.setSemaphore(yResourceSphore);
executorService.execute(yThread );
break;
}else if (zResourceSphore.tryAcquire()) {
zThread.setTask(listOfTasks.get(i));
zThread.setSemaphore(zResourceSphore);
executorService.execute(zThread );
break;
}
}
}
executorService.shutdown();
ExecutorService ExecutorService=Executors.newFixedThreadPool(3);
for(int i=0;i
我不太喜欢这个解决方案,因为如果我的资源正在执行不同类型的任务,那么它就无法扩展。因此,如果我需要一个特定类型的任务的特定资源,那么我的其他任务将持续等待,直到特定的任务完成。但是现在,我没有别的办法。即使经过这么多的研究 CPU调度程序试图将一个进程的所有线程放在同一个CPU上,以便它们可以共享缓存。但是,如何将任务分配给可用的资源呢?我正在通过信号量类的tryAcquire()方法检查资源的可用性。还有其他方法吗?根据您的建议,我在runnable中传递了信号量,并在它完成执行后释放它。但是,我仍然面临一个问题,即我无法将所有任务分配给for循环中的线程。所以我做了一个while(true)循环,直到其中一个资源可用于某个任务。然后在任务开始后打破循环。即使我找不到合适的答案,你的回答也确实有帮助