Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >如何用SingleThreadModel解决多线程安全问题

如何用SingleThreadModel解决多线程安全问题

作者头像
马克java社区
修改于 2021-07-08 06:31:15
修改于 2021-07-08 06:31:15
3460
举报
文章被收录于专栏:java大数据java大数据

2.用SingleThreadModel解决多线程安全问题:

前面介绍的都是普通的Servlet。对于每一个用户请求,那些Servlet都会用线程的方式给予应答。这样比较节省系统的资源。Sun公司也给出了另外一种方法,就是这节要介绍的SingleThreadModel的方法。当implement这个接口以后,你的Servlet就变成了另外一种模式工作。即,每一个新用户的请求,都会生成一个新的Servlet实例来应答。这种方法有两个方面的弊病。一是性能太差,最后会把机器拖累死。还有一条就是有时解决不了实际问题。每个servlet类实例都有自己独立的变量。如果我们的本意就是想让客户线程之间进行这些变量的交流。这种方法就无法做到。就像还有人建议的,用局部变量来代替类变量一样,有时也解决不了实际当中的算法问题。因为我们有时就需要用一个类似类变量一样的东西,来控制全局。即使这种方法这不好,那不好,现实中很多很多工程师也说不好。我还是给出了例子,让大家看看结果。

例:2.2.1

package com;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.SingleThreadModel;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

public class ServletHello1 extends HttpServlet implements SingleThreadModel{

int bookNum=20;

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

PrintWriter pw = response.getWriter();

while (bookNum>0){

onlySellOne(pw);

}

}

void onlySellOne(PrintWriter pw) throws IOException {

if (bookNum > 0) {

pw.println(Thread.currentThread().getName()

+ " before" + bookNum);

pw.flush();

bookNum--;

try {

Thread.sleep(2000);

} catch (Exception e) {

}

pw.println(Thread.currentThread().getName()

+ " after " + bookNum);

pw.flush();

}

}

}

更多请看:https://blog.csdn.net/qq_44594371/article/details/103163760

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何用Synchronied解决Servlet多线程安全问题?
马克-to-win:我们先铺垫Servlet的多线程基础知识。到现在为止,我们所接触到的Servlet都是这样的:第一个人访问Servlet的时候,Servlet会被实例化。之后的人再访问这个Servlet的时候,这个Servlet就不再被实例化了,而是采取线程的模式。用每一个由这个servlet而来的线程来应答来请求的客户。这样的话,Servlet的实例变量,实际上是被所有客户的线程共享的。这样就会出现线程安全的问题。一谈到多线程安全,就需要谈到我"Java初级"部分第六章的那个多线程安全的例子。这里基本还是用那个例子,只不过是放在Servlet环境下。那里对Critical data(关键数据[多个线程同时会修改的数据])的解决方案,就是在访问Critical data的方法前面加上关键字Synchronized。这里建议的解决方案也是这样。马克-to-win:我们先看一个没有加Synchonized的 critical data的例子。见下面例:2.1.1,还是像"Java初级"部分第六章那里一样,onlySellOne对于一个人来讲,一次只能卖一本书。对于本例来讲,我们用一个浏览器模拟一个人。观察浏览器,我们发现,对于有的人(http-8080-Processor25)来讲,开始还是18本书,买了一本书之后(调用一次onlySellOne),自己一看,还剩下16本书。这里显然出现了问题。问题就在于,有其他人同时也在买书。关键数据(bookNum)可以被多个线程同时修改。对于例:2.1.2,我们通过在onlySellOne方法前面加上Synchronized关键字,使得这个方法,在被任何线程调用时,其他线程就不能再调用,而只能排队等候。这样,结果就完美了。即使两个浏览器是同时运行的,数据也是一个一个减下来的。
马克java社区
2021/07/08
4140
Filter的线程安全问题
马 克-to-win:和Servlet一样,为了提高性能,Filter也采取多线程模式。即:每一个线程来应答一个用户浏览器,而且这个线程和用户要访问 的目标Servlet的线程是同一个线程。说得更准确一点,当用户访问某个资源需要经过过滤器时,服务器中一个线程为了应答这个客户请求,先调用过滤器中 的doFilter方法,再根据是否有chain.doFilter的指令,决定是否调用目标资源的doXXX方法,当然肯定还由这同一个线程调用。马克 -to-win:执行完doXXX方法以后,自然要继续完成doFilter方法里面chain.doFilter语句后面的语句,这就和基本的C语言里 主程序调用子程序的规则一样了。
马克java社区
2021/07/30
7160
浏览器客户端和Servlet如何互传参数?
马克-to-win:观察上一个例子,可以发现这么 一句话:doGet(HttpServletRequest request, HttpServletResponse response)。这句话比较难,我来解释一下。我们可以参考一下下图。当用户在浏览器输入Servlet地址,按回车以后,通过网络,Tomcat就 会运行用户这个Servlet的doGet方法,而且传入两个参数。一个就是代表从客户端来的request。另外一个就是代表从服务器去客户端的 resonse。这样顺理成章的,我们就可以想明白,request当中包含客户端送到服务器的数据。response包含服务器送回给客户端的数据。
马克java社区
2021/05/21
5330
Servlet jsp当中给出一个doPost例子。
马克-to-win:我们看到了doGet的用法。这节,我们看看doPost的用法。在Eclipse下,点击你项目名称左边的小十字符号,找到WebContent,右击它。New/HTML File:
马克java社区
2021/05/21
6560
讲讲session是怎么工作的,session的用法?
马克-to-win:到现在为止,我们学会了一次单独的请求和响应之间传递参数。但是如何跨越几次请求响应之间传递参数呢?比如我以马克的身份登录,这是 一次请求响应。之后买书又是一次请求响应。如何买书的时候还记得买书的人是马克,而不是张三呢?马克这个参数存在哪呢?这是跨越两次访问。Sun公司为我 们提供了HttpSession这个接口。HttpSession session = request.getSession();通过这句话,你可以得到一个与你的浏览器绑定的session对象,存在Tomcat里。这 个session对象只认你这个浏览器,之后只要是你这个浏览器发出的请求,无论跨越多少次请求响应,这个session对象就对它开放,其它浏览器不能 访问。通过session.setAttribute()可以往session里面存值,session.getAttribute可以取值。问题是 session是如何识别你的浏览器呢?初学者可忽略:靠Cookie或者URL改写:如果浏览器支持Cookie,则使用Cookie;如果浏览器不支持Cookie或者Cookie功能被关闭,则自动使用URL改写方法。拿cookie来说(通常客户很少见关闭cookie,即使你关了,我也可以发现,之后提醒你打开或编程序重写URL),服务器往客户端写东西时,cookie会带上sessionid。当客户端再次访问服务器时,同一path下,会自动在html请求头中带上cookie信息,服务器可以在_COOKIE域中得取到想要的sessionid。
马克java社区
2021/07/07
6550
HttpServlet的Service方法到底是怎么回事?
马克-to-win:谈到doGet,很多同学心中可能有疑问,为什么html的用户的GET的请求,会被Servlet的doGet方法处理呢?这就谈到了HttpServlet的Service方法。它的功能就是调用与HTTP请求的方法相对应的do功能。例如,如果HTTP请求方法为GET,则调用doGet() 。这样作为Servlet编写者的你,只需覆盖doGet方法。这也是我们迄今为止的做法。有 意思的是,假如用户有Get请求,但我们没有覆盖doGet的方法,会怎么样?HttpServlet的Service方法就会调用 HttpServlet的doGet方法,那个doGet方法什么也不做,所以也不会报错。(这时我们如果覆盖了doGet方法,我们的doGet方法会 被调用,请复习继承的语法)通常我们的做法是,不覆盖service方法,只覆盖相应的do方法就可以了。但有人就想覆盖service方法, service又什么都没干,那会发生什么?那样的结局就是,即使你也同时覆盖了do方法,你的do方法永远不会被调用。我们可以看看以下的实验,无论怎 么运行,输出的结果只有“service”,而“doGet”永远输出不了。
马克java社区
2021/05/21
7220
sendRedirect和RequestDispatcher的区别?
马克-to-win:response.sendRedirect()与request.getRequestDispatcher().forward()区别:response.sendRedirect(url)是先回到客户端,再重新请求url,和过去的请求没关系。可以访问任何地方。浏览器的地址栏也变成了新的url。request.getRequestDispatcher().forward()就干脆没回到客户端,就一直在服务器里,从本个web应用的一个资源(servlet,jsp,或html)跳到另一个资源。(所以不能随便访问什么地方)。而且浏览器地址栏没有变。同时可以用request.setAttribute("requestkey","requstvalue1");来传递参数。
马克java社区
2021/07/08
4060
ServletRequest.getRequestDispatcher和ServletContext.getRequestDispatcher的区别。
马克-to-win: javax.servlet.RequestDispatcher是Sun公司编写的一个Interface,顾名思义,它可以把用户请求"a资源"的request派遣(dispatch)到"b资源"上,从而实现跳转。(本来人家要访问'a资源",你的程序却让人家自动的跳转到"b资源"上。) 注意:RequestDispatcher有两种形式:这两种形式都能达到跳转的目的。一种是ServletRequest.getRequestDispatcher(String url)。一种是ServletContext.getRequestDispatcher(String url)。但正常来讲,二者都只能访问同一web应用的资源。见下面理论论述和实验。
马克java社区
2021/07/08
4440
Servlet如何凭空制造一个图像Image?
import javax.servlet.ServletOutputStream;
马克java社区
2021/07/09
2750
Servlet和Image如何做出一个验证码程序的完整版的源码?
马克-to-win: 根据上面程序,我做了一个验证码程序的大概。所有的技术点都已经涵盖了。有兴趣的同学可以自己把完整版的验证码程序做出来。
马克java社区
2021/07/09
2780
Referer是怎么用的,在Servlet当中请给出一个例子?
马克-to-win:我要是帮你卖出产品。我是不是不能白劳动?是不是该拿提成?对,没错。用户经过我的网站跳到你的网站上,买了你的东西,应该给我提成。这件事情用Servlet如何实现呢?下面就给出一个例子。如果经过AAA.html跳转到我们的Servlet,我们就打印“给他提成”。如果直接访问我们的Servlet,而没有经过任何其他页面跳转过来的。我们就打印“不用给任何人提成”。其实实现这个技术的关键就在于:html的Header当中有一个叫做Referer的键,取他对应的值就可以了。
马克java社区
2021/07/09
5430
请给出一个MVC模式下用Servlet和jsp分页的HelloWord实际的例子?
马克-to-win:像淘宝百度这样的类似网页,我们用了很多很多。基本上就 是输入查询条件以后,符合查询条件的结果可能会成千上万。我们不能一下子把所有这些结果都列出来,只能一次显示一页。当用户按下一页的时候,才会把下一页 的内容列出来。这样不至于内存崩溃。要达到这样的效果,要用到分页技术。分页技术的核心思想就是把所有的结果放在一个ArrayList的当中(在我们的 例子当中就是ArrayList ret)。马克-to-win:这个ArrayList连同相关参数比如一共有多少行(totalNumberOfRowsInDB),每页有多少行(pageSize),当 前显示是第几页(currentPageNumber),一共有多少页(totalNumberOfPages),都放在Session当中。马克-to -win:返回到jsp后,再从Session当中取出所有这些数据,把它显示出来。注意这里数据库的每行数据都对应一个RegisterRow实例。把 所有这些实例都放在ArrayList当中。如果你觉得全部把结果放在Session当中浪费空间的话,你甚至一次只放5页,当用户访问第5页的时候,你 就再一次访问数据库,把数据放在Session当中。算法由你自己定义,据情况而定。当然,为简单起见,我们的例子是把所有符合条件的数据都给取出来。
马克java社区
2021/07/14
3650
Servlet和JDBC如何配合使用请给一个例子?
马克-to-win:回去参考我java部分的jdbc部分的知识。(我把那里的例子搬到了这里)
马克java社区
2021/07/09
4270
Servlet如何与图像或图片Image做交互?
本节介绍Servlet如何与图像或者图片做交互。在现实当中,我们常见的最重要的应用就是登录时,有时管你要验证码,省得你是机器人黑客在登录,无限的试用户名和密码。还有应用就是:html当中无法显示中文图片时。
马克java社区
2021/07/09
5900
Filter与Session配合的简单过渡例子
马克-to-win:因为下一个登录例子太难,我先给出一个过度的例子,便于大家理解下一个例子。这里也有个轶事,当我在做下一个登 录的例子时,发现一个非常隐晦的bug。那就是,我本应写成:response.sendRedirect("http: //localhost:8080/ServletHello/home.jsp")。但我实际写成了:response.sendRedirect ("http://localhost:8080//ServletHello/home.jsp");多写了一个/,跳转没出现问题。严重的问题就是 filter当中怎么也取不出session了。我当时还以为是tomcat出现问题了或是机器出现毛病。这个Bug的隐晦之处是,url写错后,不是跳 转出现毛病,而是Filter当中session取不出来。我曾经一度怀疑,是sun公司整个filter机制设计有问题?后来经过仔细思考,我的结论 是,当url只是简单错误时(比如home.jsp写成home1.jsp),会跳转失败。马克-to-win:但如果只是机器名后多加了一个/,sun 公司会认为你要跳转去别的web应用,于是就把session清空了。但是filter不管是一个斜杠还是两个斜杠,还是会照常过滤。跳转去别的web应 用,所以取不到session。(请参考我的Session部分:跨应用取session)看来,sun公司的filter大的方面设计没问题,只是还是 有一点点bug。应该在下一个版本把这个问题解决一下。(应该两个斜杠就不过滤了)
马克java社区
2021/07/30
4020
Java面试题:Servlet是线程安全的吗?
Servlet不是线程安全的。 要解释为什么Servlet为什么不是线程安全的,需要了解Servlet容器(即Tomcat)使如何响应HTTP请求的。 当Tomcat接收到Client的HTTP请求时,Tomcat从线程池中取出一个线程,之后找到该请求对应的Servlet对象并进行初始化,之后调用service()方法。要注意的是每一个Servlet对象再Tomcat容器中只有一个实例对象,即是单例模式。如果多个HTTP请求请求的是同一个Servlet,那么着两个HTTP请求对应的线程将并发调用Servle
陈树义
2018/04/13
1.6K0
Java面试题:Servlet是线程安全的吗?
ServletRequestListener的用法和实例
import javax.servlet.ServletRequestEvent;
马克java社区
2021/08/02
7680
由浅入深,解析Java Servlet工作过程
如果是post请求的话则编写dopost函数,是get请求的话就编写doget函数。但此时web服务器还不能调用该servlet类,还需在web.xml文件中配置。
谭庆波
2018/08/10
7220
由浅入深,解析Java Servlet工作过程
url,sendRedirect当中有中文
中文当想出现在url当中,或通过网络http header或request的parameter或response传送时,得需要变成iso格式传送,到目的地后,再用GBK转换一下,人才能看懂。
马克java社区
2021/10/10
1.1K0
八、 Servlet生命周期和特性
当用户第一次访问Servlet时,由容器调用Servlet的构造器创建具体的Servlet对象。也可以在容器启动之后立刻创建实例。使用如下代码可以设置Servlet是否在服务器启动时就创建。
Qwe7
2022/07/24
2080
推荐阅读
相关推荐
如何用Synchronied解决Servlet多线程安全问题?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文