【问题标题】:Prevent multiple access of servlet in my application防止在我的应用程序中多次访问 servlet
【发布时间】:2012-09-14 10:59:24
【问题描述】:

下面给出的是配置为autosys作业的url。这调用下面给出的servlet。谁能建议我如何保护这个方法“psServiceWrapper.processHRFeed();”每次连续按此 url 10 次时,由于不正确的数据修改而被连续调用。我希望一次只能访问一个线程。

我知道我必须使用同步方法或块..我不确定如何..因为我不熟悉线程。

http://mydomain:11000/dorf/HRDORFScriptServlet?script=hrFeed


public class HRDORFScriptServlet extends HttpServlet {

private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(HRDORFScriptServlet.class);
private final String script = "script";

@Override
protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
    // TODO Auto-generated method stub
    performTask(arg0, arg1);
}

@Override
protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
    // TODO Auto-generated method stub
    performTask(arg0, arg1);
}

 /** Execute the servlet.
 * 
 * @param request
 * @param response
 * @throws ServletException
 * @throws IOException
 */
public void performTask(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {

    DorfUser dorfUser = DorfSessionUtils.getDorfUser(request.getSession());
    HRDorfFeedServiceWrapper psServiceWrapper = new HRDorfFeedServiceWrapper(dorfUser);
    String reqParam = request.getParameter(script);
    if(reqParam.equals("hrFeed")){
    try{
        psServiceWrapper.processHRFeed();           
    }
    catch(ServiceException se){
        log.error("Error While calling HRFeed Service : "+se.getMessage());
    }
    catch(Exception e){
        log.error("Error While calling HRFeed Service : "+e.getMessage());
    }

    }
 }

}

【问题讨论】:

    标签: java multithreading synchronization


    【解决方案1】:

    我会将psServiceWrapper.processHRFeed() 的功能移到一个实现 Runnable 的简单类中。

    public class MyTask implements Runnable
    {
        public void run() 
        {
            psServiceWrapper.processHRFeed();
        }
    }
    

    然后创建一个固定线程池大小为1的ExecutorService。

    ExecutorService psServiceRunner = Executors.newFixedThreadPool(1);
    

    每次调用 servlet 时,我都会将 MyTask 的实例发布到这个实例。

    psServiceRunner.execute(new MyTask());
    

    这会

    1. 不要阻止您的 servlet 调用者。
    2. 确保任何时候只有一个 servlet 可以运行该方法。

    【讨论】:

      【解决方案2】:
      synchronized(this){ 
       psServiceWrapper.processHRFeed();     
      }
      

      但这会导致瓶颈,因为您的 servlet 将停止响应,直到当前线程执行 psServiceWrapper.processHRFeed();

      如果您使用的是 Java 5,您也可以ReetrantLock

      具有与使用同步方法和语句访问的隐式监视器锁相同的基本行为和语义的可重入互斥锁,但具有扩展功能。

         private final ReentrantLock lock = new ReentrantLock();//Declare it
      

      像下面这样使用它

       lock.lock();  // block until condition holds
       try {
         psServiceWrapper.processHRFeed();
       } finally {
         lock.unlock()
       }
      

      【讨论】:

      • 本文中提到的序列化访问确实可以解决您的问题,但会牺牲应用程序的活力。您的实际问题是 processHRFeed() 方法不是并发的。如果性能在您的项目中有意义并且您可以访问该方法的实现(也就是说,如果您可以修改它),我建议您调查是否可以重新设计该方法以便由并发线程安全运行。
      猜你喜欢
      • 2022-01-02
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      • 2012-01-19
      相关资源
      最近更新 更多