2014-12-22 38 views
-5

![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秒之后,所有的线程都会死亡过程最终停止 测试进行查找原因:

  1. 试图重现有留言板较小的代码问题 - 一个线程等待字符串改变,另一种改变它 - didnt导致问题
  2. 对同一对象犯规notifyAll的做重现的问题,如果没有线程等待它
  3. 使用其他对象作为锁尝试 - 问题presists

的信息:使用jdk1.7.0_71在Windows 7上运行64位在Eclipse上

任何帮助将不胜感激

回答

0

这行:ExecutorService ex=Executors.newCachedThreadPool();创建一个线程池。 这行:CreateStaySimulationForClient stay=new CreateStaySimulationForClient(cs,request.getDuration()); 大概是,创建一些东西,使用该线程池。

您在剪切中提到的线程是来自该池的线程之一。它确实有一个名称,里面有“pool”,这样你就知道它来自哪里:)

另外,请注意,你正在这样做(线程池创建)在一个循环中,这几乎肯定是不是你想做什么。

+0

显然 - 我以前怎么没有想到它?谢谢! – asafb