badass_programmer
badass_programmer

Reputation: 105

java.lang.Thread.State: BLOCKED (on object monitor)

There are too many Threads in Blocked State in my thread Dump.This makes My application unresponsive.When I looked into the code I found that the function is synchronized due to which thread go in block state.If this method is not made Synchronized then multiple threads accessing same method at the same time would cause problem like one mail thread interfere with another thread. How do i change my code in a way that My application don't have to suffer. This is my code-

//Mailtransport class

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;
}

//MailSession class

 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;
}

This is a part of my thread 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)

Upvotes: 1

Views: 5545

Answers (1)

Davide Lorenzo MARINO
Davide Lorenzo MARINO

Reputation: 26926

Here are some tips:

Don't send emails on the main thread. Create a thread pool that handle emails. This is useful because generally you don't need to wait for an email to be sent successfully to give an answer to the invoking method. Is enough to say I already took your email and I will send it as soon as possible (asynchronously).

Are you sure that you need to synchronize getNewTransport? Try to rewrite the method getNewTransport to return a new Transport without using mutable instance variables. Doing that you can eliminate the use of synchronized.

Upvotes: 1

Related Questions