Java Web服务并发问题

时间:2011-10-30 18:14:44

标签: java web-services concurrency synchronization

我有一个java方法调用Web服务并根据响应对数据库进行更改。我的任务是在多个用户同时使用此应用程序时消除并发错误。

我试图整天使用各种类型的数据库锁定,但没有任何效果。我终于尝试在进程请求方法中使用synchronized,这一切都奏效了。

我的整个应用程序都是单线程的。为什么synchronized会解决这个问题?

编辑:添加了代码。

public class ProcessMakePaymentServlet extends HttpServlet {

    private DbBean db = new DbBean();

    protected synchronized void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // defining variables...

        try {

            // initialize parameters for invoking remote method

            db.connect(); 
            startTransaction(); //autocommit=0; START TRANSACTION;
            // process debit
            //this method gets the method using a select...for update. 
            //it then updates it with the new value
            successfulDebit = debitAccount(userId, amt);
            if (successfulDebit) {
                // contact payment gateway by invoking remote pay web service method here.

                // create new instances of remote Service objects
                org.tempuri.Service service = new org.tempuri.Service();
                org.tempuri.ServiceSoap port = service.getServiceSoap();

                // invoke the remote method by calling port.pay().
                // port.pay() may time out if the remote service is down and throw an exception
                successfullyInformedPaymentGateway = port.pay(bankId, bankPwd, payeeId, referenceId, amt);

                if (successfullyInformedPaymentGateway) {
                    // insert payment record
                    recordPaymentMade(userId, amt, referenceId); 
                    //call to the database to record the transaction. Simple update statement.
                    out.println("<br/>-----<br/>");
                    //getTotalPaymentMade does a select to sum all the payment amounts
                    out.println("Total payment made so far to gateway: " + getTotalPaymentMade());
                    commitTransaction();// calls COMMIT
                    db.close(); //connection closed.
                } else {
                    rollbackTransaction();//calls ROLLBACK
                    db.close();
                    successfulDebit = false;
                    out.println("<br/>-----<br/>");
                    out.println("Incorrect bank details.");
                }
            } else {
                rollbackTransaction();//calls ROLLBACK
                db.close();
                out.println("<br/>-----<br/>");
                out.println("Invalid payment amount.");
            }


        } catch (Exception ex) {
            try {
                rollbackTransaction();//calls ROLLBACK
                db.close();
            } catch (Exception ex1) {
            }
        }

  }

2 个答案:

答案 0 :(得分:2)

  

我的整个应用程序都是单线程的。为什么同步解决   此?

不,它不是单线程的。 Web服务由接收客户端请求的多个线程调用。

Web服务方法实现必须处理所有同步问题,与接收多个请求的servlet实现相同,必须注意确保线程安全。

在您的情况下,通过添加synchronized,您确保Web服务客户端请求的并发处理不会因线程问题而导致损坏,并且您实际上是序列化客户端请求(以及对数据库的访问)。

你还没有发布任何代码来查看你做错了什么,但是由于web方法级别的同步解决了你的问题,你要么没有像你说的那样在数据库级别进行同步,要么线程问题损坏公共变量在访问数据库的Web服务层。

通过Web方法的synchronizing,代码是线程安全的,但性能会恶化,因为您一次只能为1个客户端服务。

取决于您的要求

答案 1 :(得分:0)

private DbBean db = new DbBean();移到servlet方法中,这应该可以解决问题并发问题:

protected void processRequest(HttpServletRequest request, ...) {

  // defining variables...
  DbBean db = new DbBean();

...
}

尽管如此,您应该正确清除finally块中的所有数据库资源。一个相当简单的例子,但我希望你明白我的意思:

protected void processRequest(HttpServletRequest request, ...) {

  // defining variables...
  DbBean db = null;
  boolean commit = false;

  try {
    db = new DbBean();
  } catch (SomeException e) {
    commit = false;
  } finally{
    db.release(commit); /* close database connection => java.sql.Connection#close() */
  }

...
}