Java 多线程:分配和阻塞资源的问题

Java 多线程:分配和阻塞资源的问题,java,multithreading,Java,Multithreading,我有多种资源——为了理解,比如说3种资源,即XResource、YResource和ZResource(Java类-Runnables),它们能够完成特定的任务。在这三种资源中有一个需要并行完成的任务列表。我需要锁定资源,如果其中一个资源被锁定,那么任务应该转到其他资源,如果没有任何资源可用,那么它应该等到其中一个资源可用。我目前正在尝试使用信号量获取资源的锁,但是线程只被分配给一个可运行线程,而其他可运行线程总是空闲的。我对多线程非常陌生,所以我可能忽略了一些显而易见的东西。我正在使用Java

我有多种资源——为了理解,比如说3种资源,即XResource、YResource和ZResource(Java类-Runnables),它们能够完成特定的任务。在这三种资源中有一个需要并行完成的任务列表。我需要锁定资源,如果其中一个资源被锁定,那么任务应该转到其他资源,如果没有任何资源可用,那么它应该等到其中一个资源可用。我目前正在尝试使用信号量获取资源的锁,但是线程只被分配给一个可运行线程,而其他可运行线程总是空闲的。我对多线程非常陌生,所以我可能忽略了一些显而易见的东西。我正在使用JavaSE1.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();
}
}
公共类测试{
私有最终静态信号量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)循环,直到其中一个资源可用于某个任务。然后在任务开始后打破循环。即使我找不到合适的答案,你的回答也确实有帮助