Javaweb学习笔记之HttpServlet(四):Servlet 的多线程并发问题

Servlet 的多线程并发问题:

package com.demo.f_thread;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
 * Servlet 的多线程并发问题:
 * 如果多个线程同时访问了 servlet 对象的共享数据(成员变量),则可能会引发线程安全问题,因为 Servlet 是单实例多线程的。
 */

@WebServlet("/ThreadDemo1")
@SuppressWarnings("serial")
public class ThreadDemo1 extends HttpServlet {

	private int count = 1; // 成员变量(共享数据)
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=utf-8");
		

		// 如果线程1执行完输出语句,还没有执行 count++ 语句,
		// 线程2就抢到了执行权,执行输出语句,那么线程1和线程2输出的 count 值都是 1.
		resp.getWriter().write("你是当前网站的第" + count + "个访客。");
		
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		count++;
		
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
	
}

Servlet 的多线程并发解决办法:

package com.demo.f_thread;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
 * Servlet 的多线程并发问题:
 * 如果多个线程同时访问了 servlet 对象的共享数据(成员变量),则可能会引发线程安全问题,因为 Servlet 是单实例多线程的。
 * 解决办法:
 * 	1、把使用到共享数据(如成员变量)的代码块进行同步(使用 synchronized 关键字进行同步)
 * 	2、建议在 servlet 类中尽量不要使用成员变量。如果使用了成员变量,必须要同步,而且尽量缩写同步代码块的范围,
 * 		因为同步会降低多线程并发的效率。(哪里使用了成员变量,就同步哪里!!!)
 */

@WebServlet("/ThreadDemo1")
@SuppressWarnings("serial")
public class ThreadDemo1 extends HttpServlet {

	private int count = 1; // 成员变量(共享数据)
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=utf-8");
		
		// 锁对象必须是唯一的,建议使用 类对象。
		// 锁中的内容同一时间只允许一个线程执行,其他线程需等待;必须等一个线程执行完了,另一个线程才能执行。
		synchronized (ThreadDemo1.class) {

			// 没有使用 synchronized 锁的情况下:如果线程1执行完输出语句,还没有执行 count++ 语句,
			// 线程2就抢到了执行权,执行输出语句,那么线程1和线程2输出的 count 值都是 1.
			resp.getWriter().write("你是当前网站的第" + count + "个访客。");
			
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			count++;
		}
		
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
	
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值