以下是代码:
final CountDownLatch lineDirectionLatch = new CountDownLatch(count);
final Object lock = new Object();
for(StationLines station : stationList) {
final String gpsNumber = station.getGpsNumber();
for(String lineNumber : station.getLines()) {
final TranslateToStationTask task = new TranslateToStationTask(lineNumber, gpsNumber);
task.setCallback(new Runnable() {
@Override
public void run() {
synchronized (lock) {
Utils.debug(TAG, "Thead " + Thread.currentThread().getId() + " enter critical section.");
int errorCode = task.getTaskResult().getErrorCode();
if (errorCode == 0) {
Station station = task.getTaskResult().getContent();
if (station != null) {
for(int idx = 0; idx < stationList.size(); idx++) {
String gpsNumber = stationList.get(idx).getGpsNumber();
if (gpsNumber.equals(station.getGpsNumber())) {
stationList.get(idx).setDirection(station.getLineNumber(), station.getDirection());
}
}
}
}
Utils.debug(TAG, "Thead " + Thread.currentThread().getId() + " leave critical section.");
lineDirectionLatch.countDown();
}
}});
task.startTask();
}
}
lineDirectionLatch.await();
Herer是日志:
03-26 19:57:07.648: I/TrafficManager(20013): Thead 1501 enter critical section.
03-26 19:57:07.687: I/TrafficManager(20013): Thead 1501 leave critical section.
03-26 19:57:07.714: I/TrafficManager(20013): Thead 1502 enter critical section.
03-26 19:57:07.722: I/TrafficManager(20013): Thead 1502 leave critical section.
03-26 19:57:07.726: I/TrafficManager(20013): Thead 1503 enter critical section.
03-26 19:57:07.726: I/TrafficManager(20013): Thead 1503 leave critical section.
03-26 19:57:07.769: I/TrafficManager(20013): Thead 1509 enter critical section.
03-26 19:57:07.773: I/TrafficManager(20013): Thead 1505 enter critical section.
03-26 19:57:07.773: I/TrafficManager(20013): Thead 1505 leave critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1506 enter critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1506 leave critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1507 enter critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1507 leave critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1510 enter critical section.
03-26 19:57:07.843: I/TrafficManager(20013): Thead 1511 enter critical section.
03-26 19:57:07.843: I/TrafficManager(20013): Thead 1513 enter critical section.
你可以看到线程1505进入关键部分而不是先前输入的线程(1509),并且线程1509永远不会离开关键部分?这很奇怪。
每个TranslateToStationTask都在它自己的线程中运行,当任务完成它的工作时,将调用临界区。
我不知道为什么关键部分允许多个任务进入,以及为什么某些任务似乎永远不会离开关键部分?
答案 0 :(得分:4)
从您的代码中看起来您正在函数本身中创建lock
对象。
因此,每次调用该函数时,都会有一个针对不同线程的新锁。
因此他们都将进入你的关键部分。
要获得所需的行为,请将其移出此功能。
答案 1 :(得分:2)
请在synchronized块中添加一个try-catch子句,以查看该函数是否异常,从而在不事先通知的情况下解锁对象。
类似的东西:
synchronized(lock) {
try {
// my code
}
catch (Exception e) { // generic catch to look if any exception is triggered
System.out.printf("Caused exception: %s",e.getMessage());
}
}
另一个可能的问题是您使用新的Runnable()创建一个匿名类,因此锁可能并不总是相同的变量。尝试创建一个实现Runnable的类和lock变量,并调用该构造函数。
答案 2 :(得分:0)
线程1509没有将关键部分留在日志中的任何位置。也许它等待lock
,什么会允许其他线程进入临界区? (不太可能,因为lock
似乎没有在代码片段中的方法之外的任何地方传递。)