我做了一些重新排列,但在调试语句之后,似乎这就是您试图完成的。我删除了一些用于测试的代码,并改为列表而不是数组。
位置类。
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Location
implements Runnable
{
private final int id;
private final List<Integer> dependentLocationIds;
private final Lock lock = new ReentrantLock();
private boolean isUnlocked = true;
public Location(int id, List<Integer> dependentLocationIds)
{
this.id = id;
this.dependentLocationIds = dependentLocationIds;
Collections.sort(dependentLocationIds);
}
public int getId()
{
return id;
}
public List<Integer> getDependentLocationIds()
{
return dependentLocationIds;
}
public boolean isUnlocked()
{
return isUnlocked;
}
public boolean blockLocation()
{
lock.lock();
isUnlocked = false;
System.out.printf("Location: %d occupied by: %s\n", this.getId(),
Thread.currentThread().getName());
return isUnlocked;
}
public boolean releaseLocation()
{
lock.unlock();
isUnlocked = true;
System.out.printf("Location: %d released by: %s\n", this.getId(),
Thread.currentThread().getName());
return isUnlocked;
}
public void occupy()
{
while (!LocationHelper.acquireLocks(this))
{
try
{
System.out.printf("Location: %d sleeping during occupy on: %s\n",
this.getId(), Thread.currentThread().getName());
Thread.sleep(1500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
// below sleep added to track the progress slowly
Thread.sleep(1000);
System.out.printf("Location: %d doing something on: %s\n", this.getId(),
Thread.currentThread().getName());
}
catch (InterruptedException e)
{
e.printStackTrace();
LocationHelper.releaseLocks(this);
}
}
public void leave()
{
try
{
// below sleep added to track the progress slowly
Thread.sleep(1000);
System.out.printf("Location: %d is attempting to leave on: %s\n",
this.getId(), Thread.currentThread().getName());
LocationHelper.releaseLocks(this);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
LocationHelper.releaseLocks(this);
}
}
public void run()
{
occupy();
leave();
}
public static void main(String[] args)
{
List<Location> locations = LocationHelper.getLocations();
for (Location location : locations)
{
// Each location runs in different threads here
new Thread(location, "THREAD-" + location.getId()).start();
}
}
}
LocationHelper类
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class LocationHelper
{
private static List<Location> holdsLocks = new ArrayList<Location>();
private static final List<Location> locations = new ArrayList<>();
private static int printLocks = 0;
static
{
locations.add(new Location(1, Arrays.asList(1, 2, 3, 4, 5)));
locations.add(new Location(2, Arrays.asList(1, 2, 3, 4)));
locations.add(new Location(3, Arrays.asList(1, 2, 3, 4)));
locations.add(new Location(4, Arrays.asList(3, 4, 5)));
locations.add(new Location(5, Arrays.asList(1, 2, 3, 4, 5)));
}
public static List<Location> getLocations()
{
return locations;
}
public static Location getLocation(int id)
{
return locations.stream().filter(l -> l.getId() == id).findFirst()
.orElse(null);
}
public static synchronized boolean acquireLocks(Location location)
{
if (printLocks % 5 == 0)
{
locations.stream()
.forEach(l -> System.out.printf("Location: %d status: %s\n",
l.getId(), String.valueOf(l.isUnlocked())));
}
List<Location> required = location.getDependentLocationIds().stream()
.map(LocationHelper::getLocation).collect(Collectors.toList());
// If not available fail to lock.
if (required.stream().filter(l -> !l.isUnlocked()).count() > 0L)
{
return false;
}
else
{
try
{
required.stream().forEach(Location::blockLocation);
holdsLocks.add(location);
return true;
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
required.stream().forEach(Location::releaseLocation);
return false;
}
}
}
public static boolean releaseLocks(Location location)
{
if (!holdsLocks.contains(location))
{
return false;
}
else
{
List<Location> required = location.getDependentLocationIds().stream()
.map(LocationHelper::getLocation).collect(Collectors.toList());
try
{
required.stream().forEach(Location::releaseLocation);
holdsLocks.remove(location);
return true;
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
}
}