Множество объектов, неизвестных до выполнения, как блокировки для потока Java - PullRequest
2 голосов
/ 10 марта 2019

У меня есть набор ресурсов, которые являются экземплярами класса Resource.В системе выполняются задания, поступающие во время выполнения.Каждое задание требует набора этих ресурсов и должно эксклюзивно использовать все ресурсы, необходимые для его продолжения.То есть, чтобы задание могло быть запущено, оно должно получить блокировки всех ресурсов, которые ему необходимы, и освободить все эти блокировки, которые оно получило, как только оно выполнено.Таким образом, задание не может начать свою обработку, если не доступны все блокировки всех необходимых ему ресурсов.

Ресурсы, необходимые для работы, неизвестны до выполнения.Список ресурсов, необходимый для работы, передается в его конструктор как Collection ArrayList<Resource>.

Одним из способов сделать это является то, что в методе run() каждого потока задания я могу синхронизировать все блокировки ресурсов, в которых нуждается это задание.

synchronized (resource1) {
    synchronized (resource2) {
        ...

    }
}

Но это жесткое кодирование, и его невозможно выполнить, поскольку ресурсы, необходимые для работы, известны только во время выполнения.

Другой способ, который я могу придумать, - это поместить ресурсы в структуру коллекции, чтобы при получении блокировки этой коллекции блокировались все записи в этой коллекции, и они никому не были доступны.остальное.

Есть Collections.synchronizedList().Однако он блокирует только List, а не объекты в списке.

Как это можно сделать?

TIA.

Ответы [ 2 ]

1 голос
/ 10 марта 2019

Как насчет использования цикла, вы перебираете список Resources, доступный во время выполнения, а затем получаете блокировку объектов на одну итерацию, вот пример, где я демонстрирую это с классом Object:

public static void main(String[] args) {
       List<Object> list = new ArrayList<>();
       list.addAll(Arrays.asList(new Object(), new Object(), new Object()));
       Runnable run = () -> {
           for(Object o: list) {
               synchronized (o) {
                   System.out.println("Current thread " + Thread.currentThread().getName());
                   System.out.println(o.hashCode());
                   try {
                       Thread.sleep(2000);
                   }catch (InterruptedException ie){
                       ie.printStackTrace();
                   }
                   //do something useful
               }
           }
       };
       new Thread(run, "t1").start();
       new Thread(run, "t2").start();
       new Thread(run, "t3").start();
       new Thread(run, "t4").start();
 } 

Когда один поток получил блокировку для определенного объекта, другие потоки будут ожидать его, но они могут получить блокировку для следующего доступного объекта из цикла for-each.

0 голосов
/ 10 марта 2019

Вы можете написать собственную реализацию интерфейса List и заблокировать ресурсы, когда они запрашиваются в списке.

https://docs.oracle.com/javase/8/docs/api/java/util/List.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...