![在这里输入图像描述] [1]有没有人知道为什么在notifyall之后释放锁时会创建新线程? 我有一个线程正在侦听请求状态(STRING)以进行更改(等待锁定对象),另一个线程正在更改它:
@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 profiler我得到了线程转储,他们都显示:
"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秒后,所有螺纹都会死亡,最后一个过程停止 测试完成以确定原因:
获取信息:在eclipse上运行的Windows 7 x64上使用jdk1.7.0_71
任何帮助将不胜感激
答案 0 :(得分:0)
这一行:ExecutorService ex=Executors.newCachedThreadPool();
创建一个线程池。
这一行:CreateStaySimulationForClient stay=new CreateStaySimulationForClient(cs,request.getDuration());
据推测,使用该线程池创建一些东西。
你在snipped中提到的线程是该池中的一个线程。它确实有一个名字,它有&#34; pool&#34;在其中,以便你知道它来自哪里:)
另外,请注意您在循环中执行此操作(创建线程池),这几乎肯定是不您想要执行的操作。