关于controller的一点疑问
一般情况下,spring中的controller是单例模式的,也就是说所有的访问都会调用同一个controller的方法,自然而然的就会想到并发的问题,当某一个请求调用controller方法尚未退出时,是否会造成后续请求的阻塞。
写个小demo测试一下
@RequestMapping("/dotest01/{id}")
@ResponseBody
public String dotest01(@PathVariable("id") int id) {
long start =System.currentTimeMillis();
String str;
if(id==1) {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.info("1号"+Thread.currentThread().getName());
log.info(this.toString());
str="1号结果!";
}else {
log.info("2号"+Thread.currentThread().getName());
log.info(this.toString());
str="2号结果";
}
long time =System.currentTimeMillis()-start;
return str+time;
}
进行测试先发送访问dotest01/1,后访问dotest01/2,很明显第一个页面尚在加载,第二个就已经返回
再看看后头的对象
很明显,线程是单独的但是controller是同一个。
可以确认的是,不用考虑controller的阻塞问题,再写一个多线程测试案例
public class TestThread {
public static void main(String[] args) {
MyTool tool = new MyTool();
new Thread(new MyThread(0, tool)).start();
new Thread(new MyThread(1, tool)).start();
}
}
class MyThread implements Runnable {
private int id;
private MyTool tool;
public MyThread(int id,MyTool tool) {
this.id=id;
this.tool=tool;
}
public void run() {
long start = System.currentTimeMillis();
System.out.println("Thred:"+Thread.currentThread().getName()+"=="+tool.toString());
tool.dosome(id);
long time = System.currentTimeMillis()-start;
System.out.println("id"+id+"==time="+time);
}
}
class MyTool {
public void dosome(int id) {
if(id ==0) {
System.out.println("00开始工作!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("00工作完成!");
}else {
System.out.println("01开始工作!");
System.out.println("01工作完成!");
}
}
}
测试结果为
符合期望,工作线程不同,工作对象同一个。在修改一下
public synchronized void dosome(int id){
.....
}
为方法加上锁,这时候就不同了,
此时线程才会阻塞,说到底对阻塞的概念有点混乱,多线程是可以同时访问通一个不加锁方法,所谓额并发问题是多线程操作造成的数据混乱,阻塞是加锁造成的,很显然controller并未给方法加锁,所以并不会有阻塞的问题。
但是也得注意,在controller中创建全局变量这时候就要考虑并发问题了。