Spring事务管理的一些基础知识
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 |
//通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值。 private
static ThreadLocal<Integer> tdLocal = new
ThreadLocal<Integer>(){ public
Integer initialValue(){ return
0 ; } }; //获取下一个序列值。 public
int getNextNum(){ tdLocal.set(tdLocal.get()+ 1 ); return
tdLocal.get(); } //私有的测试线程类。 private
static class TestClient extends
Thread{ private
SequenceNum seqNum; public
TestClient(SequenceNum seqNum){ this .seqNum = seqNum; } public
void run(){ for ( int
i= 0 ;i< 3 ;i++){ System.out.println( "Thread is [" + Thread.currentThread().getName() + "],序列号是 " + seqNum.getNextNum()); } } } public
static void main(String[] args) { SequenceNum seqNum = new
SequenceNum(); TestClient client1 = new
TestClient(seqNum); TestClient client2 = new
TestClient(seqNum); TestClient client3 = new
TestClient(seqNum); TestClient client4 = new
TestClient(seqNum); //运行线程。 client1.start(); client2.start(); client3.start(); client4.start(); } ================================================== Thread is [Thread- 1 ],序列号是 1 Thread is [Thread- 2 ],序列号是 1 Thread is [Thread- 0 ],序列号是 1 Thread is [Thread- 3 ],序列号是 1 Thread is [Thread- 3 ],序列号是 2 Thread is [Thread- 0 ],序列号是 2 Thread is [Thread- 2 ],序列号是 2 Thread is [Thread- 2 ],序列号是 3 Thread is [Thread- 1 ],序列号是 2 Thread is [Thread- 0 ],序列号是 3 Thread is [Thread- 3 ],序列号是 3 Thread is [Thread- 1 ],序列号是 3 |
我们看到这四个线程共享了同一个SequenceNum实例,但是线程之间并没有相互的影响,而是各自产生独立的序列号,不存在线程安全性的问题,这是因为我们通过ThreadLocal为每一个线程提供了单独的变量副本。这也是Spring解决线程安全的机制。
????
书中有一句话很生动形象的对比了同步机制和ThreadLocal解决线程安全问题不同点:对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式:访问串行化,对象共享化;而ThreadLocal采用了“以空间换时间”的方式:访问并行化,对象独立化。前者提供一份变量,让不同的线程排队访问,而后者为每一份线程提供了一份变量,因此可以同时访问而互不影响。
Spring使用ThreadLocal解决线程安全的问题。
我们大概都有这么一个概念,只有无状态的Bean才能在多线程环境下共享,在Spring中,绝大部分的Bean都可以声明为singleton作用域。因为Spring对一些Bean(如RequestContextHolder,TranscationSynchronizationManager,LocalContextHolder)中非线程安全的“状态性对象”采用ThreadLocal进行封装,把他们变成线程安全的“状态性对象”,因此有状态的Bean能够以Singleton的方式在多线程中正常工作了。这里小可我说一下我的具体感受:原来Spring注入的JdbcTemplate是单例模式!其实就一个模板对象,把他注入到多个Service中,原来怎么没有注意到这一点呢?还有对有状态对象的理解,这个说的直白一点就是这个变量在不同的线程中不一样,尼玛取了一个有状态对象(变量)感觉好迷糊人啊!呵呵
看看书中对多线程的理解:
一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写不同的逻辑,下次通过接口向上层开发接口调用。在一般的情况下,从接收请求到返回相应所经过的所有程序调用都同属于一个线程(看到这句话,我就想到了Servlet和CGI的区别,一个请求到来Servlet就会新建一个线程去响应这个请求,而CGI则是需要新建一个进程,所以Servlet的效率更高。尼玛这是以前看过的一个面试题啊,终于对上了),如图:
这样根据需要,把一些非线程安全的变量存放到ThreadLocal中,在同一次请求响应的调用线程中,所有对象访问同一ThreadLocal变量都是当前线程绑定的。
怎么理解Spring中DAO和Service都是以单实例的bean形式存在这句话,就是不同的线程调用的都是同一个DAO和Service的实例,只有一个实例。
http://blog.csdn.net/c289054531/article/category/1473443
原文:http://www.cnblogs.com/lovery/p/3745712.html