![enter image description here] [1]有没有人有关于在notifyall后释放锁定时创建新线程的想法? 我有一个线程监听请求状态(STRING)改变(等待锁定对象),另一个变化是:通知后的Java释放锁定导致出现新线程
@Override
public void run() {
while(!customerGroupDetails.isEmpty()){
RentalRequest request=customerGroupDetails.remove();
management.addRentalRequest(request);
getLogger().info(Thread.currentThread().getName() + ": handling new request:" + request.toString());
getLogger().info(Thread.currentThread().getName() + ": waiting for request status to be FULFILLED");
request.waitForStatus("FULFILLED");
ExecutorService ex=Executors.newCachedThreadPool();
CompletionService<Double> cs= new ExecutorCompletionService<Double>(ex);
CreateStaySimulationForClient stay=new CreateStaySimulationForClient(cs,request.getDuration());
request.setRequestStatus("INPROGRESS");
getLogger().info(Thread.currentThread().getName() + ": Simulating stay and setting requets status to INPROGRESS");
customerGroupDetails.forEach(stay);
Future<Double> damage=null;
Double recivedDamage=new Double(0);
double sum=0;
int numberOfCustomers=customerGroupDetails.size();
for(int i=0;i<numberOfCustomers;i++){
try {
damage=cs.take();
recivedDamage=damage.get();
getLogger().info(" damage for assetContent is " + recivedDamage);
sum=sum+recivedDamage;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
getLogger().info(Thread.currentThread().getName() + ": Asset is damaged by " + sum);
request.getAsset().damage(sum);
if(request.getAsset().getHealth()<65){
management.changeAssetStatus(request.getAsset(), "UNAVILABLE");
DamageReport damageReport=new DamageReport(request.getAsset(), sum);
management.addDamageReport(damageReport);
}
else{
management.changeAssetStatus(request.getAsset(), "AVAILABLE");
getLogger().info(request.getAsset() + " is now available");
}
request.setRequestStatus("COMPLETE");
getLogger().info(Thread.currentThread().getName() + ": damage report has been submitted to managment - this request status is COMPLETE");
}
getLogger().info(Thread.currentThread().getName() + ": no more requests for me - i'm done");
}
@Override
public void run() {
int totalTime = 0;
boolean shiftEnded = false;
getLogger().info(clerkDetails.toString() + ": starting new shift");
while (!shiftEnded&& !Thread.currentThread().isInterrupted()) {
RentalRequest req = null;
getLogger().info(clerkDetails.toString() + ": trying to take request");
try {
req = rentalRequests.take();
} catch (InterruptedException e) {
if (numberOfRequests.get() == 0) {
getLogger()
.info(clerkDetails.toString()
+ " was interrupted becuase there are no more requests");
shiftEnded=true;
} else {
getLogger().warning(
clerkDetails.toString()
+ " was interrupted unexpectedly"
+ e.toString());
}
}
if (req!=null) {
int num=numberOfRequests.decrementAndGet();
getLogger().info(clerkDetails.toString() + ": recived request: "+req.toString()+",number of requests left is " +num +", now finding appropreiate asset");
Asset asset = assets.getAsset(req.getAssetType(),
req.getAssetSize());
assets.changeAssetStatus(asset, "BOOKED");
getLogger().info(clerkDetails.toString() + ": Asset " + asset.toString() + " is now BOOKED");
req.setAsset(asset);
management.updateEarnings(asset.getCostPerNight()
* req.getDuration());
int time = getClerkDetails().getLocation().calculateDistance(
asset.getLocation());
totalTime = totalTime + time;
getLogger().info(clerkDetails.toString() + ": going to Asset - sleeping:" + time);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
getLogger().warning(
clerkDetails.toString()
+ " was interrupted unexpectedly"
+ e.toString());
}
req.setRequestStatus("FULFILLED");
getLogger().info(clerkDetails.toString() + ": request status set to: FULFILLED");
getLogger().info(clerkDetails.toString() +": time left for this shift is " + (8 -totalTime));
if (totalTime > 8) {
shiftEnded = true;
}
if (numberOfRequests.get() == 0) {
shiftEnded=true;
management.interrupt();
getLogger().info(clerkDetails.toString() + ": finished last requets for this simulation - tyring to interrupet managment");
}
}
}
management.countDownClerksBarriar();
getLogger().info(clerkDetails.toString() + ": finished shift");
}
public void setRequestStatus(String status) {
synchronized(statusLock){
//if(!getRequestStatus().equalsIgnoreCase(status)){
requestStatus = status;
statusLock.notifyAll();
//}
}
}
public void waitForStatus(String status){
synchronized (statusLock) {
while(!getRequestStatus().equalsIgnoreCase(status)){
try {
statusLock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
一切工作正常,除了锁释放后创建新主题, 使用的VisualVM探查我得到了线程转储,它们都显示:
"pool-15-thread-2" prio=6 tid=0x000000000c20e000 nid=0x23d8 waiting on condition [0x00000000112be000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000e0badf08> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(Unknown Source)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(Unknown Source)
at java.util.concurrent.SynchronousQueue.poll(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- None
不用说 - 我所创建的线程有名字,所以我知道它不是其中之一, 所有我创建的线程是完成在30-40秒之后,所有的线程都会死亡过程最终停止 测试进行查找原因:
- 试图重现有留言板较小的代码问题 - 一个线程等待字符串改变,另一种改变它 - didnt导致问题
- 对同一对象犯规notifyAll的做重现的问题,如果没有线程等待它
- 使用其他对象作为锁尝试 - 问题presists
的信息:使用jdk1.7.0_71
在Windows 7上运行64位在Eclipse上
任何帮助将不胜感激
显然 - 我以前怎么没有想到它?谢谢! – asafb