2016-12-01 717 views
1

在我的線程轉儲中阻塞狀態中的線程太多。這使得我的應用程序無響應。當我查看代碼時,發現該函數是同步到期的哪個線程進入阻塞狀態。如果這個方法沒有被同步,那麼多個線程同時訪問同一個方法會導致像一個郵件線程干擾另一個線程的問題。我如何以我的應用程序不必遭受的方式更改我的代碼。這是我的代碼 -java.lang.Thread.State:BLOCKED(在對象監視器上)

// Mailtransport類

public final boolean openConnection() throws MailingException { 
    boolean flag = false; 

    if (transport == null) { 

     mailsession = MailSession.getMailSession(); 
     try { 
      transport = (SMTPTransport) mailsession.getNewTransport(); 
      flag = true; 
      // System.out.println("\n--MailTransport.java ------------ Connection is SUccessful -- "+transport.isConnected()); 
     } catch (MailingException mex) { 
      setStatusmessage(new StringBuffer(statusMessages[1]).append(
        " -- ").append(mailsession.getSmtphost()).append(
        "<BR> Contact").append(
        "<A HREF=\"mailto:" + returnPath + "\">").append(
        "Administrator").append("</A>").toString()); 
      throw mex; 
     } 
    } else { 
     flag = true; 
    } 
    return flag; 
} 

//郵件會話類

public synchronized Transport getNewTransport() throws MailingException 
{  
    try 
    { 
     return getNewTransport(mailtype); 

    } catch (MailingException e) 
    { 
     throw e; 
    } catch (Exception e) 
    { 
     throw new MailingException(" Exception in MailSession.getTransport ", e); 
    } 
} 





public static MailSession getMailSession() 
{ 
    MailSession _mailSession = MultiTenancyUtil.getTenantMailSession(); 
    if (_mailSession == null) 
    { 
     synchronized (MailSession.class) 
     { 
      if (_mailSession == null) 
      { 
       _mailSession = new MailSession(); 
       _mailSession.initialize(); 
       MultiTenancyUtil.getTenantResources().setMailSession(_mailSession); 
      } 
     } 
    } 
    return _mailSession; 
} 





    public Transport getNewTransport(String type) throws MailingException 
{ 
    Transport transport = null; 
    try 
    { 
     transport = session.getTransport(type); 
     if (StringUtil.isvalidInteger(getSmtpprot())) 
     { 
      transport.connect(getSmtphost(), Integer.parseInt(getSmtpprot()), username, password); 
     } else 
     { 
      transport.connect(getSmtphost(), username, password); 
     } 
    } catch (MessagingException ex) 
    { 
     MailingException mailex = null; 
     Exception nex = ex.getNextException(); 
     if (nex != null) 
     { 
      if (nex instanceof SocketTimeoutException) 
      { 
       mailex = new SMTPServerException("Connection to Server Failed. SMTP server does not Exist on host--" + getSmtphost() + " -- Mention the proper Host. Other wise Server is very Slow"); 
       mailex.setCause(ex); 
      } 
      if (nex instanceof ConnectException) 
      { 
       mailex = new SMTPServerException("Connection to Server Failed. Unable to connect to port" + getSmtpprot() + " on SMTP server host---" + getSmtphost() + " -- Mention the proper Server and Port."); 
       mailex.setCause(ex); 
      } 
     } 
     if (mailex == null) 
     { 
      mailex = new SMTPServerException("Connection to Server Failed"); 
      mailex.setCause(ex); 
     } 

     throw mailex; 
    } catch (Exception ex) 
    { 
     MailingException mailex = new MailingException("Connection to Server Failed"); 
     mailex.setCause(ex); 
     throw mailex; 
    } 
    return transport; 
} 

這是我的線程的dump-

 at javax.mail.Service.connect(Service.java:275) 
    at javax.mail.Service.connect(Service.java:156) 
    at  com.appnetix.app.util.mail.MailSession.getNewTransport(MailSession.java:199) 
    at com.appnetix.app.util.mail.MailSession.getNewTransport(MailSession.java:249) 
locked <0x00000007211b9480> (a com.appnetix.app.util.mail.MailSession) 
    at com.appnetix.app.util.mail.MailTransport.openConnection(MailTransport.java:122) 
    at com.appnetix.app.util.mail.MailSenderBase.init(MailSenderBase.java:107) 
    at com.appnetix.app.util.MailSender.sendMail(MailSender.java:193) 
    at com.appnetix.app.util.MailSender.sendMail(MailSender.java:175) 

回答

1

這裏有一些部分提示:

Don'在主線程上發送電子郵件。創建一個處理電子郵件的線程池。這很有用,因爲通常您不需要等待電子郵件成功發送以回答調用方法。足以說我已經收到了你的電子郵件,我會盡快發送(異步)。

您確定需要同步getNewTransport嗎? 嘗試重寫方法getNewTransport以返回新的Transport而不使用可變實例變量。這樣做可以消除​​的使用。

+0

刪除可變實例變量如何幫助使其不同步並正常工作? –

+0

代碼只需要同步以訪問可以被多個線程更改的變量。如果您有單線程應用程序同步是沒有必要的。如果您有多線程應用程序,但共享變量不可修改,則不需要同步。 –