JAVA线程/并发/请求的关系是怎么样的?精华
最近对线程并发请求有疑惑,度娘了一大圈,找了一些精华,真的很精华!!!!在此总结记录下:
转载连接如下:
https://bbs.csdn.net/topics/360170441
https://bbs.csdn.net/topics/360170441
https://www.zhihu.com/question/41737405/answer/100743322
https://www.cnblogs.com/GtShare/p/8033637.html(Servlet如何处理多个请求访问?下一篇马上进行搬运)
https://blog.csdn.net/weixin_39939904/article/details/114207476
用过socket就知道,很多用户同时发出请求,在一个时间点服务器只能处理一个用户的请求,如果你没有采用多线程的话,那么服务器只有处理完
当前用户的请求之后,才能处理下一个用户的请你。如果用了多线程,那么下个用户请求时就不用等到上个用户处理完再处理,而是可能某个时间点会切换到当前用户的请求处理。如果多线程之间没有数据共享,那么可以不用synchronized。
单线程和多线程的区别是在于 你每次是否操作同一个线程 如果是多线程 那么你读代码就会明白 每次 操作的是重新创建的线程
保证线程安全 有三种方式: 第一种 用ThreadLocal 定义变量 , 第二种 用同步锁 也就是你说的synchronized , 还有一种springmvc 和spring整合做项目的时候,注解的开发方式,就是使用局部变量,随着方法的消失而消失
1.多个用户访问同一段代码算多线程吗?
2.那怎么样控制并发?
不是, 多用户请求是并发,并发是多个用户或者说多个请求要同时对同一条记录进行操作,和是不是同一段代码没关系。好比说多个用户同时登陆一个系统时,都需要用到登陆的相关代码,是不会发生什么冲突的。好比说对一个财务系统,两个人同时对总钱数进行操作,一个加10块一个减100块,注意这两个操作是同时进行的,那系统就不知道是加还是减了,这是并发问题。加锁解决就是,在一个请求开始对这条记录操作时,其它的请求就不能对它操作了,直到现在正在进行的操作完成。
并发 和多线程之间联系和区别?
并发与多线程之间的关系就是目的与手段之间的关系。并发(Concurrent)的反面是串行。串行好比多个车辆行驶在一股车道上,它们只能“鱼贯而行”。而并发好比多个车辆行驶在多股车道上,它们可以“并驾齐驱”。并发的极致就是并行(Parallel)。多线程就是将原本可能是串行的计算“改为”并发(并行)的一种手段、途径或者模型。因此,有时我们也称多线程编程为并发编程。当然,目的与手段之间常常是一对多的关系。并发编程还有其他的实现途径,例如函数式(Functional programming)编程。多线程编程往往是其他并发编程模型的基础,所以多线程编程的重要性不言而喻。
controller中的全局变量如何解决????
Controller默认是单例的,不要使用非静态的成员变量,否则会发生数据逻辑混乱。 正因为单例所以不是线程安全的。
如下代码:
package com.riemann.springbootdemo.controller;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ScopeTestController {
private int num = 0;
@RequestMapping("/testScope")
public void testScope() {
System.out.println(++num);
}
@RequestMapping("/testScope2")
public void testScope2() {
System.out.println(++num);
}
}
我们首先访问 http://localhost:8080/testScope,得到的答案是1; 然后我们再访问 http://localhost:8080/testScope2,得到的答案是 2。
得到的不同的值,这是线程不安全的。
接下来我们再来给Controller增加作用多例 @Scope(“prototype”)
package com.riemann.springbootdemo.controller;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@Scope("prototype")
public class ScopeTestController {
private int num = 0;
@RequestMapping("/testScope")
public void testScope() {
System.out.println(++num);
}
@RequestMapping("/testScope2")
public void testScope2() {
System.out.println(++num);
}
}
我们依旧首先访问 http://localhost:8080/testScope,得到的答案是1; 然后我们再访问 http://localhost:8080/testScope2,得到的答案还是 1。
相信大家不难发现 :
单例是不安全的,会导致属性重复使用。
解决方案
1、不要在Controller中定义成员变量。 2、万一必须要定义一个非静态成员变量时候,则通过注解@Scope(“prototype”),将其设置为多例模式。 3、在Controller中使用ThreadLocal变量