精华内容
下载资源
问答
  • web开发需要解决线程问题吗
    千次阅读
    2018-08-24 16:10:22

    在web应用中,每次请求都是不同的线程,因此,当对统一数据进行访问更新的时候,有可能会引发数据问题。

    举个例子:有一个apple表,里面有个字段count,表示某种apple的数量。同时,后台提供获取这种苹果的服务,获取苹果之后,就需要将count的值修改。

    假设apple表中有这么一条数据
    id      count
    12345   100
    ----------
    
    
        class Apple{
            int count;
        }
    
        public interface AppleMapper{
            @Select("select count from apple")
            Apple getApple();
    
            @Update("update apple set count = #{count}")
            void updateCount(int count);
        }
    
        service:
        public void getApple(int num) {
        //step1
        Apple apple = appleMapper.getApple();
        //取走num个苹果后剩下count个苹果,假设num<getCount()
        int count = apple.getCount() - num;
        //step2
        appleMapper.updateCount(count);
        }

    现在,有两条请求,都想获得苹果,req1.getApple(5)和req2.getApple(6);如果req1在step2完成后,req2才到达step1,那么数据库结果没有任何问题,但是,一旦req2在req1执行万step2时,就执行了step1,那么此时,req2.getCount() = 100,req1.count = 95,req2.count = 94,此时,无论哪个count存入数据库,都将是错误的,实际的count应该是89。

    解决办法:
    不要在业务逻辑中计算,然后将计算结果传入数据库,可传入需要改变的值,数据库sql改为”update apple set count = count + #{num}”。
    还有种不推荐的方法:以在stept1处获得的值作为条件,如果数据库的值和我在step1处取出的值一致,说明没有人修改这个值,那么就更新,否则不更新。

    这样的场景其实也不是很常见,一般前端将最终结果传入,只更新最终结果,就没这种问题了。最后,切记,遇到更新数值的操作时,不要在逻辑里计算,并将结果作为最终值更新,应该交由数据库去处理。

    更多相关内容
  • WEB API 多线程并发测试工具; WEB API 多线程并发测试工具
  •  WEB服务器会帮你把每个访问请求开辟一个线程,你只要按照你所开发的框架,比如tomcat会让你利用servlet这个框架来写代码。具体真的一言难尽,反正不用写到RUN中,除非你想对线程控制到极致,例如你要做测试。 ...
        1. web应用中,要对某一个任务用多线程实现,最简单的代码格式是不是必须把要执行的代码放在run方法中?

        WEB服务器会帮你把每个访问请求开辟一个线程,你只要按照你所开发的框架,比如tomcat会让你利用servlet这个框架来写代码。具体真的一言难尽,反正不用写到RUN中,除非你想对线程控制到极致,例如你要做测试。


        2. 部署在服务器上的一个网站,多个浏览器在访问同一个功能点时,存在多线程之说吗?

        多个浏览器的意思如果是(无论多台电脑上还是同一台电脑上的)多个页面打开同一网站的某个功能页面,那么如第一个问题所说,每一次访问(即打开页面)都是一个请求,服务器会为每个请求开辟一个线程,就是多线程。


        3. 多线程和并发之间是怎么一种关系?

        多线程执行效率就是评判并发效果的好坏,高并发的概念就是在保证数据准确的情况下,减少进程所需操作的时间,特别经典的是页面访问服务器后,让服务器去修改数据库,如果你的数据库优化做的到位,那么查找数据并返回给客户端的时间将大大减少,我们知道对于一个热门网站的查询量是非常大的,然后一个服务器内存可以接收的进程数量也是有限的,这样一来,我们就说某一时间段内处理线程(访问请求)越多,那么并发效率就越好了。


        4. 对于经典的买票程序,是因为要操作共同资源而是用多线程技术,那么对于一些平常的查询显示功能就没必要用多线程技术。对于这里发起的多个查询请求,是多个线程吗?

        买票程序应用与WEB就应该是多线程,共同资源存放在数据库中,和第三个问题的回答类似,这种商业性的站点更侧重于保证数据准确性,有时候我们修改的某项值会影响到别人的查询与增删,于是意外情况就产生了,例如在一个A线程(用户)正在修改某项值(买票)的情况下,要减少1张的剩余票总量是不准确的,因为当这个用户在方法中对获得的总剩余票数的同时(以获得总剩余票数,但还未减一),另一个B线程(用户)也进行买票,那么B获得的总剩余票数与A是相同的,因此他们如果同时被允许操作数据库的公共资源,那么当两人都只想完购票的减一操作时,第三线程或其他线程的查询剩余票量将只会看到原本减少2张剩余量,实际只少了一张,可以想象如果操作的线程越多,误差将会更大。因此数据库才会有事务,锁等等概念来提高确保数据准确性前提下的并发效率


        5. 如何解决WEB开发多线程抢夺问题 —— synchronized

        Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

        1)当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

        2)然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

        3)尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

        4)第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

        5)以上规则对其它对象锁同样适用.

    展开全文
  • 线程web中的使用

    千次阅读 2018-09-28 15:01:05
    整理网络上的 最典型的如: ... 且这类任务即使失败也不是特别重要的。 2、后台线程:比如定期执行一些特殊任务,如定期更新配置文件,任务调度(如...上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理...

    整理网络上的

    最典型的如:
    1、用户注册完成送大礼包/积分之类,且积分等也是另一个系统并比较耗时;
    且这类任务即使失败也不是特别重要的。

    2、后台线程:比如定期执行一些特殊任务,如定期更新配置文件,任务调度(如quartz),一些监控用于定期信息采集等。

    回答二:
    最典型的应用比如tomcat,tomcat内部采用的就是多线程。
    上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用到我们的servlet程序,比如doGet或者doPost方法。
    如果不采用多线程机制,上百个人同时访问一个web应用的时候,tomcat就得排队串行处理了,那样客户端根本是无法忍受那种访问速度的。

    还有就是需要异步处理的时候,需要使用多线程。
    比如task a和task b要并行处理,单个线程只能串行处理,先做完task a然后再做task b。

    如果想要多个task同时执行的话,就必须为每个task分配一个线程,然后通过java虚拟机的线程调度,来同时执行多个任务。

    比如你的CPU是多核心的话,就可以让一个CPU执行一个线程。
    如果只有一个CPU的话,底层是按照分时复用的原则,各个线程按照时间片来获得CPU资源。

    回答三:

    特别耗时的操作

    如备份数据库,可以开个线程执行备份,然后执行返回,前台不断向后台询问线程执行状态问

    JAVA项目中哪些场景需要用到多线程,深感迷茫,请使用过的高手指点。

    场景一:
    一个业务逻辑有很多次的循环,每次循环之间没有影响

    比如验证1万条url路径是否存在,正常情况要循环1万次,逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。

    这时可以用多线程,将1万条URL分成50等份,开50个线程,每个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。

    场景二:

    需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。

    总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个业务逻辑执行效率特别低,耗时特别长,就可以考虑使用多线程。

    不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级

    因此使用多线程的风险也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!

    最典型的如:1、用户注册完成送大礼包/积分之类,且积分等也是另一个系统并比较耗时;且这类任务即使失败也不是特别重要的。2、后台线程:比如定期执行一些特殊任务,如定期更新配置文件,任务调度(如quartz),一些监控用于定期信息采集等。回答二:最典型的应用比如tomcat,tomcat内部采用的就是多线程,上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用到我们的servlet程序,比如doGet或者doPost方法。如果不采用多线程机制,上百个人同时访问一个web应用的时候,tomcat就得排队串行处理了,那样客户端根本是无法忍受那种访问速度的。还有就是需要异步处理的时候,需要使用多线程。比如task a和task b要并行处理,单个线程只能串行处理,先做完task a然后再做task b。如果想要多个task同时执行的话,就必须为每个task分配一个线程,然后通过java虚拟机的线程调度,来同时执行多个任务。比如你的CPU是多核心的话,就可以让一个CPU执行一个线程。如果只有一个CPU的话,底层是按照分时复用的原则,各个线程按照时间片来获得CPU资源。回答三:特别耗时的操作,如备份数据库,可以开个线程执行备份,然后执行返回,前台不断向后台询问线程执行状态问:JAVA项目中哪些场景需要用到多线程,深感迷茫,请使用过的高手指点。答:场景一:一个业务逻辑有很多次的循环,每次循环之间没有影响,比如验证1万条url路径是否存在,正常情况要循环1万次,逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。这时可以用多线程,将1万条URL分成50等份,开50个线程,没个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。场景二:需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个业务逻辑执行效率特别低,耗时特别长,就可以考虑使用多线程。不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级,因此使用多线程的风险也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!


    有一些比较耗时,但又很重复的工作可以多线程。

    比如入库,入库时很耗时的。但如果入库的数据已准备好,并且很多。多线程就好一些。

    比如同步数据,你不知道什么时候对方会给你传递数据过来,这个时候你就间隔一段时间让他自己去执行,其实还涉及一些逻辑上的处理比较耗的。这样不影响你其他地方的处理……

    (1)线程的工作场景主要有两条:
    一个是并发操作,避免阻塞和更有效利用资源。典型的例子有:在长时间工作的程序中使用工作线程避免界面失去响应。在网络下载程序中,使用多个线程提高对网络的使用效率,更快下载文件。
    一个是并行,线程是处理器调度的最小单位。如果你的计算机配置了多个处理器或者内核,那么可以同时利用多个处理器同时计算,加快问题解决的速度。
    (2)多线程的工作原理:
    对于单处理器系统,操作系统会轮流调度每个线程执行一小段时间,然后切换另一个线程,在切换的时候,保存当前线程使用的寄存器上下文和堆栈,并且在下次调度的时候恢复。这样线程中的程序感觉不到自己被中断过。对于多处理器系统,操作系统会将不同的线程调度给多个处理器,让它们并行执行。

    这个要用,由很多可用的,看你的程序结构,发邮件是一个,假如你的文档管理系统要做全文索引,那么在用户上传一个文件后,后台要做索引,就可以启动一个线程去创建索引,还有如果你的文档管理系统权限比较复杂,涉及文件夹父子关系权限的继承和覆盖等复杂的ACL操作,都可以使用多线程。

    1、单线程和多线程区别:
    单线程处理的优点:同步应用程序的开发比较容易,但由于需要在上一个任务完成后才能开始新的任务,所以其效率通常比多线程应用程序低,如果完成同步任务所用的时间比预计时间长,应用程序可能会不响应。
    多线程处理可以同时运行多个过程,简单说下多线程开发的益处:
    1.多线程开发可以将耗时操作放入子线程,将UI刷新加入主线程,防止页面卡顿。
    2.在并发操作时使用多线程,如C/S架构的服务器端并发线程响应用户的请求。
    3.在多核CPU系统中,使用线程可以提高程序响应速度,提高CPU和内存的利用率。
    4.改善程序结构。将一个复杂的的进程分为多个线程,减少类之间的耦合。
    5.将程序分块管理,方便程序的开发和维护。
    6.可以随时停止任务。 可以分别设置各个任务的优先级以优化性能。
    2、开启多线程
    一个请求就是一个线程,这个线程不需要我们来控制,WEB容器自己实现,这是第一个应用。
    我们也可以在web中new线程来做我们的事。比如,当我有一个很耗时的操作,像统计排名之类的功能。当用户在web上点击排名时,由于这个计算量太大,可能要计算3~5分钟或更久。这时我们会在servlert中new一个线程来做这个事情,这样用户就可以点击排名后去做其他的事,等排名出来现通知他。如果不new线程当用户点排名时,浏览器就会一直卡在这里,一个圈圈转啊转的,就是不出来。所以我们可以new线程来做耗是任务。还有很多比如,定时任务、WEB版的爬虫程序、监听等
    3、场景一:一个业务逻辑有很多次的循环,每次循环之间没有影响,比如验证1万条url路径是否存在,正常情况要循环1万次,逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。这时可以用多线程,将1万条URL分成50等份,开50个线程,没个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。
    场景二:需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。
    场景三:电商项目中controller层需要接收前台传来的需要下架商品id,因为是全选操作所以也就是数据库中商品表的所有id。然后调用service层业务逻辑进行删除。本人数据库中商品表大概有3000条数据,在不考虑多线程方式下,速度已经明显受到影响,实际项目中又何止成千上万条数据!如果单线程逐一进行删除其性能可想而知。所以考虑创建多个线程,多线程并发形式执行商品下线业务逻辑。
    总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个业务逻辑执行效率特别低,耗时特别长,就可以考虑使用多线程。不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级,因此使用多线程的风险也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!

    为什么要使用多线程?
    1.防止阻塞主线程,提高吞吐量
    2,提高资源的利用率
    应用场景:
    1,最典型的应用比如tomcat,tomcat内部采用的就是多线程,上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用到我们的servlet程序,比如doGet或者doPost方法。

    2,做登录业务时使用到sms短信网关业务,创建子线程,让子线程去调用sms服务,主线程则返回,这样做可以提高用户的体验度
    3,图片上传业务
    4

    项目中如何使用多线程
    多线程在项目中主要用来解决并发任务执行。java中线程的主要实现方式有三种:继承Thread类 实现Runnable接口 实现Callable接口。另外还可以通过Executor类来创建多线程线程池。
    线程生命周期:首先通过继承thread或者实现runnable接口来创建一个线程,当调用线程的start方法,线程进入就绪状态,如果这时处理器有资源运行此线程,线程就进入运行状态,如果线程内部调用了sleep就会放弃cpu资源,返回到阻塞状态,线程等待某个通知,sleep时间到了之后,如果其他线程发送通知,那么当前线程就从阻塞状态变为就绪状态恢复执行。另如果调用了yield()方法也会从运行状态变为就绪状态。一般来说线程执行完毕或者调用stop方法线程结束生命周期。
    四种模板线程池:1可缓存线程池 newCachedThreadPool 2定长线程池 newFixedThreadPool 3定长支持定时及周期性任线程池, newScheduledThreadPool 4单线程化的线程池(有序) newSingleThreadExecutor 。我们在项目中主要使用了第二种就是定长线程池newFixedThreadPool,一般多线程进行并行任务处理需要配合队列使用。队列中存放任务信息,当线程池中的线程进行任务处理,主动去队列领取任务,队列将任务弹出并交由线程执行,所有线程谁先执行完,就领取行的任务,直到队列中没有任务。
    线程安全:一般通过加锁解决安全问题,保证数据一致性。一般我们可以使用synchronized标记方法或者代码块,来保证原子性操作。但是synchronized性能不如volatile。 在java底层中一些设计线程安全的源码都是用了volatile关键字。多线程如果要保证数据安全必须要保证原子性、可见性以及有序性。一般情况下当多个线程同时执行时,如果多个线程同时访问同一变量,如果变量所在方法没有使用synchronized,将导致每个线程只关注自己线程内cache的变量值,当多个线程将变量同步到主线程的主存时,会发生数据不一致的情况。如果使用volatile可以让变量拥有可见性,多个线程进行执行时,每个线程都会看到主线程中的主存的变量值发生的改变,进行修正,保证与自己线程数据同步,在线程修改变量时,volatile关键字会强制将修改的值立即写入主存,其他线程中的对应缓存变量就会被强制标记为无效,而从主存中进行同步。

    项目业务场景:
    批量页面静态化 在系统中,商品详情页我们使用freemarker来进行页面静态化,每天夜里12点开始要对所有商品页面进行一遍静态化,由于商品数量比较多 如果使用单线程将耗时过长,我们使用一个定长线程池进行批量执行,将任务放在队列中,多个线程同时领取并执行。

    订单处理(用户下单后可能支付状态不明确,我们后台可以通过多线程去主动核实第三方支付状态,来更新我们系统的订单状态)
    登录后用户信息处理(用户登录后应该通知各相关系统将用户常用数据进行缓存 以快速响应登录用户),

    大CC的博客

    内容目录:
    多进程模型多线程模型选用参考

    多线程和多进程模型的选用
    这里的线程指通过linux的pthread_create而产生的原生线程,线程资源很宝贵,能被操作系统的任务调度器看见的(不是python gevent、go gorouine里的概念);
    我们讨论以下两种模型;
    多进程单线程模型(以下简称为多进程);单进程多线程模型(以下简称为多线程);多进程模型
    优点
    编程相对容易;通常不需要考虑锁和同步资源的问题。
    更强的容错性:比起多线程的一个好处是一个进程崩溃了不会影响其他进程。
    有内核保证的隔离:数据和错误隔离。
    对于使用如C/C++这些语言编写的本地代码,错误隔离是非常有用的:采用多进程架构的程序一般可以做到一定程度的自恢复;(master守护进程监控所有worker进程,发现进程挂掉后将其重启)
    多进程的案例
    nginx主流的工作模式是多进程模式(也支持多线程模型)
    几乎所有的web server服务器服务都有多进程的,至少有一个守护进程配合一个worker进程,例如apached,httpd等等以d结尾的进程包括init.d本身就是0级总进程,所有你认知的进程都是它的子进程;
    chrome浏览器也是多进程方式。
    redis也可以归类到“多进程单线程”模型(平时工作是单个进程,涉及到耗时操作如持久化或aof重写时会用到多个进程)
    多线程模型
    优点
    多线程优点:创建速度快,方便高效的数据共享
    共享数据:多线程间可以共享同一虚拟地址空间;多进程间的数据共享就需要用到共享内存、信号量等IPC技术;
    较轻的上下文切换开销 - 不用切换地址空间,不用更改寄存器,不用刷新TLB。
    提供非均质的服务
    如果全都是计算任务,但每个任务的耗时不都为1s,而是1ms-1s之间波动;这样,多线程相比多进程的优势就体现出来,它能有效降低“简单任务被复杂任务压住”的概率;
    适用的场景
    1 线程间有数据共享,并且数据是需要修改的(不同任务间需要大量共享数据或频繁通信时);
    2 提供非均质的服务(有优先级任务处理)事件响应有优先级;
    3 单任务并行计算,在非CPU Bound的场景下提高响应速度,降低时延;
    4 与人有IO交互的应用,良好的用户体验(键盘鼠标的输入,立刻响应)
    多线程案例
    桌面软件,响应用户输入的是一个线程,后台程序处理是另外的线程;
    memcached
    选用
    单进程多线程和多进程单线程,2种模式如何取舍?
    进程线程间创建的开销不足作为选择的依据,因为一般我们都是使用线程池或者进程池,在系统启动时就创建了固定的线程或进程,不会频繁的创建和销毁;
    首先,根据工作集(需要共享的内存)的大小来定;如果工作集较大,就用多线程,避免cpu cache频繁的换入换出;比如memcached缓存系统;
    其次,选择的依据根据以上多线程适用的场景来对比自身的业务场景,是否有这样场景需求:数据共享、提供非均质的服务,单任务拆散并行化等;
    如果没有必要,或者多进程就可以很好的胜任,就多用多进程,享受单线程编程带来便利;
    RCU的发明者,Paul McKenny 在《Is Parallel Programming Hard, And, If So, What Can You Do About It?》说过:
    能用多进程方便的解决问题的时候不要使用多线程。
    参考
    ref:《Linux多线程服务端编程:使用muduo网络库》
    ref:http://www.zhihu.com/question/19903801
    ref:https://computing.llnl.gov/tutorials/pthreads/#WhyPthreads


    本文来自 RoyKuang07 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/pirlck/article/details/52296716?utm_source=copy

    本文来自 Xiayubing_ 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/Xiayubing_/article/details/81381704?utm_source=copy

    本文来自 袖扣 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/Sundefind/article/details/79062239?utm_source=copy

    本文来自 fmwind 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/fmwind/article/details/77068706?utm_source=copy
    参考链接

    https://blog.csdn.net/kangkang_hacker/article/details/80863359?utm_source=copy

    展开全文
  • Servlet的线程安全问题

    千次阅读 2022-02-04 11:27:13
    文章目录Servlet的线程安全问题引入Servlet的多线程机制如何修复1.实现 SingleThreadModel 接口2.避免使用成员变量3.同步对共享数据的操作思考与小结参考文章 Servlet的线程安全问题 引入 首先看看这样的代码,有...

    Servlet的线程安全问题

    引入

    首先看看这样的代码,有什么问题

    这里既要求cmd不能包含Calculator又必须要包含Calculator,能做到吗,当然是可以的

    在这里插入图片描述

    Servlet的多线程机制

    Servlet实际上是一个单件,当我们第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件或者是注解实例化这个Servlet类,之后如果又有新的客户端请求该Servlet时,则一般不会再实例化该Servlet类,这说明了什么呢?简单来说,当多个用户一起访问时,得到的其实是同一个Servlet实例,这样的话,他们对实例的成员变量的修改其实会影响到别人,所以在开发的时候如果没有注意这个问题往往会有一些额安全问题,而往往Servlet的线程安全问题主要是由于实例变量使用不当而引起

    因此我们再看上面的代码,很明显我们看到了这个status状态变量是实例变量,当然这里为了突出并发的效果,这里加了一个延时,这里简简单单用python实现竞争,也不必上多线程了简单点

    url = "http://127.0.0.1:8080/?cmd=open -na Calculator"
    
    while 1:
        r = requests.get(url)
        if "Cal" in r.text:
            print(r.text)
    
    url = "http://127.0.0.1:8080/?cmd=ls"
    
    while 1:
        r = requests.get(url)
    

    在这里插入图片描述

    如何修复

    1.实现 SingleThreadModel 接口

    该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。这种方法只要继承这个接口就行了,因此将我们上面的代码改为

    public class TestServlet extends HttpServlet implements SingleThreadModel 
    

    这样你觉得就完全安全了吗??答案也不是,如果我们将上面的对状态的定义加上static呢

    public static boolean status;
    

    lol,还是可以成功,原因是SingleThreadModel不会解决所有的线程安全隐患。会话属性和静态变量仍然可以被多线程的多请求同时访问

    在这里插入图片描述

    还有一点很重要该接口在Servlet API 2.4中将不推荐使用。

    2.避免使用成员变量

    既然问题出自成员变量,那么我们就尽量避免去使用它

    将上面的代码改为

    public class TestServlet extends HttpServlet{
    
    //    public  boolean status;
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            boolean status = true;
            String cmd = req.getParameter("cmd");
            if (cmd.contains("Calculator")) {
                status = false;
                try {
                    Thread.sleep(1000);
                }catch (Exception e){
    
                }
            }
    
            if (!status) {
                return;
            }
            if (cmd.contains("Calculator")){
                resp.getWriter().write(cmd);
            }
        }
    }
    

    3.同步对共享数据的操作

    使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段,因此可以将代码写为

    public class TestServlet extends HttpServlet{
    
        public  boolean status;
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            String cmd = req.getParameter("cmd");
            boolean status;
            synchronized(this) {
                status = true;
    
                if (cmd.contains("Calculator")) {
                    status = false;
                    try {
                        Thread.sleep(5000);
                    } catch (Exception e) {
    
                    }
                }
            }
    
            if (!status) {
                return;
            }
            if (cmd.contains("Calculator")){
                resp.getWriter().write(cmd);
            }
        }
    }
    

    思考与小结

    但是如果利用上面三种方式去修复,这样就完全没问题了吗?并不是

    比如实现SingleThreadModel以及在程序中使用同步来保护要使用的共享的数据,在实际业务当中这也会使得我们系统的性能大大下降,这也是我们不太希望看到的,前者为每个新的请求创建一个单独的Servlet实例,这将引起大量的系统开销,而后者被同步的代码块在同一时刻也只能有一个线程执行它,这也会导致在高并发的情况下,同时处理请求的吞吐量显著的降低

    因此,在Serlet中避免使用实例变量或许是更好的选择,但如果无法避免,但如果无法避免,也应该尽量做到去同步可用性最小的代码路径

    参考文章

    https://www.cnblogs.com/chanshuyi/p/5052426.html

    https://zhuanlan.zhihu.com/p/93708538

    https://www.jianshu.com/p/06260e0667a9

    展开全文
  • 在互联网业务发展非常迅猛的早期,如果预算不是问题,强烈建议使用“增强单机硬件性能”的方式提升系统并发能力,因为这个阶段,公司的战略往往是发展业务抢时间,而“增强单机硬件性能”往往是最快的方法。...
  • 对于从事后端开发的同学来说,问题是我们每天都需要考虑的问题线程安全问题通俗的讲:主要是在多线程的环境下,不同线程同时读和写公共资源(临界资源),导致的数据异常问题。比如:变量a=0,线程1给该变量+1,...
  • 它提供了JavaScript多线程解决方案 这个新特性叫做Web Worker (在此之前没有多线程,setTimeout等本质仍然是单线程) 虽然是多线程编程 不过我们不用担心传统的多线程语言C++、Java等等遇到的多线程问题 ...
  • 【Javaweb】线程安全详解

    千次阅读 2022-02-28 16:16:53
    一、观察线程的所有状态 线程的状态是一个枚举类型 Thread.State public static void main(String[] args) { for (Thread.State state : Thread.State.values()){ System.out.println(state); } } NEW: ...
  • 2021年Django Web开发框架依然值得选择吗?

    万次阅读 多人点赞 2020-12-01 16:28:40
    需要使用UWSGI或Gunicorn创建足够多的运行django的工作线程来为流量提供服务,这要比node.js或FastAPI之类的解决方案效率低下且资源消耗更多,后者运行事件循环(event loop)并在需要等待时在请求之间切换任何事情...
  • 背景: 最近项目有个批量导入的需求需要优化——当导入数量过大时,后端对导入数据的校验和数据库操作时间...此处异步处理采用的是多线程的方式实现,然后就有了以下的问题。 一、多线程服务调用导致token失效 ...
  •  2:spring单例模式的安全问题是使用ThreadLocal解决的 单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。 当多用户同时请求...
  • 现代程序开发过程中不可避免会使用到多线程相关的技术,之所以要使用多线程,主要原因或目的大致有以下几个: 1、 业务特性决定程序就是多任务的,比如,一边采集数据、一边分析数据、同时还要实时显示数据; 2、 ...
  • 一文看懂Web后端开发

    千次阅读 多人点赞 2021-03-20 23:53:34
    一文看懂Web后端开发 前言 由于网络上系统地介绍后端开发的文章实在太少,而最近有恰巧有许多同学问我“什么是后端开发?”、“你为什么喜欢后端开发?”、“做后端都需要学什么?”,那么我们就来讲一讲,到底什么...
  • ,以帮助开发实现更好的并发控制。 线程通信 线程通信的目标是使线程间能够互相发送信号。另一方面,线程通信使线程能够等待其他线程的信号。 例如,线程B可以...
  • 最近的项目是关于B/S架构下的Web版PACS开发,为了缩短研发周期,采用了该领域主流的两大开源库:DCMTK和CxImage。但是由于项目初期对CxImage开源库的编译问题,导致该开源库在MFC下无法正常运行,因此决定将功能函数...
  • 【JavaWeb】解决线程安全的主要手段

    千次阅读 2021-12-20 22:57:01
    多线程编程一个需要注意的问题是线程安全问题,即多线程并发对某个资源进行修改,导致数据混乱。这也是缺乏经验的网站工程师...编程上,解决线程安全的主要手段有如下几点。 一、将对象设计为无状态对象 所谓无状态对象
  • (一)Java 多线程开发 (二)Android 多线程开发 2.1)基础使用 1、继承Thread类 (1)简介 Thread类是Java中实现多线程的具体类,封装了所需线程操作。在Android开发中用于实现多线程。 注:线程对象&运行...
  • 这里p1.name="bbb"是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向的类变量name=“aaa”,但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再...
  • servlet是否存在线程安全问题

    千次阅读 多人点赞 2018-06-12 21:21:33
    今天老师问了一句,servlet存在线程安全问题吗,心想着servlet不是单例的嘛,每个线程在调用的时候都会为实例对象分配独立的引用。我就以为servlet属于线程安全的。晚上自己再网上查看了一下,发现servlet不是安全的...
  • 它广泛用于旅行,医疗保健,交通运输,金融等不同领域,用于Web开发和软件测试,脚本编写和生成。 Python的受欢迎程度与其提供的各种好处有关,例如简单性和优雅性吸引了这些大公司。但是,尽管使用Python进行Web...
  • SpringMVC线程安全问题

    千次阅读 2018-12-12 21:07:57
    所在在使用spring开发web 时要注意,默认Controller、Dao、Service都是单例的。 @Controller  @RequestMapping("/fui")  public class FuiController extends SpringController {  //这么定义的话...
  • Java Web服务收到请求时线程的情况

    千次阅读 多人点赞 2017-05-07 17:29:15
    Web请求线程的状态在开发中,突然想到了这样的一个问题, Java对每一次Web的请求,是否都会创建一条线程去进行处理呢?也就是说,当一个Class的方法同时有1000个请求访问时,线程是如何运作的呢?解释上面的问题,...
  • 移动设备在全球范围内得到了空前的普及,在前端领域,Hybird Web、React Native、Weex、Flutter 等等一系列新的移动前端技术也如同雨后春笋般冒出来,今天来和大家分享一下我对「移动前端开发Web 前端开发」的...
  • JAVA多线程并发

    千次阅读 2022-02-17 14:41:51
    JAVA线程实现/创建方式 1.继承Thread类 Thread类本质上时实现了Runnable接口的一个实例,代表一个现成的实例。启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个...
  • Delphi(C++ Builder)一直致力于快速的应用程序开发环境已有25年以上的历史,并且仍在继续增长。如果您知道如何使用Delphi,Delphi会帮助您迅速并且能够创建任何应用程序APP及WEB网站应用! 当前,使用Delphi,您...
  • 前端进阶(十八)js多线程

    千次阅读 2019-06-25 15:05:15
    HTML5引入Web Works,让js支持多线程。 一、多线程demo 1、先写一个add函数 function(a, b){ if(a && b){ return a + b; } return 0; } 把这个函数写到works,js中 2、使用web works的钩子函数...
  • Spring使用ThreadLocal解决线程安全问题

    千次阅读 2015-01-07 12:33:52
    我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager...
  • Java多线程中程序阻塞问题排查过程

    千次阅读 2019-12-14 20:24:34
    市场反馈说数据投产功能速度太慢,需要优化,决定使用并发投产的方式,于是启用了线程池技术。但是市场在用的时候会出现项目卡死不动的情况。数量少的时候不会出现,数据量大就会出现,项目日志也停滞不前。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 205,962
精华内容 82,384
关键字:

web开发需要解决线程问题吗