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

 

你可能感兴趣的:(javaweb学习笔记)