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

时间:2015-08-16 17:52:08

标签: java multithreading

我有多个资源 - 为了理解说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();
}
}

2 个答案:

答案 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}}

我不太喜欢这个解决方案,因为如果我的资源正在执行不同类型的任务,它就无法扩展,因此如果我需要特定资源用于特定类型的任务,我的其他任务将持续等待直到特定任务任务完成。但是现在无法通过任何其他方式。即便经过这么多的研究!