- 浏览: 253263 次
- 性别:
- 来自: 沈阳
最新评论
-
wahahachuang8:
GoEasy 实时推送支持IE6-IE11及大多数主流浏览器的 ...
关于服务器推送 -
vfgvfrgvs:
引用引用引用引用引用引用引用引用引用[list][*][lis ...
一个纯java的验证码识别算法 -
656615066lkl:
[color=brown][/color]cczxCZCX
一个纯java的验证码识别算法 -
keephope:
求教一下。是不是这个程序只能分辨出间距相等的验证码的内容呢
一个纯java的验证码识别算法 -
boke_xu:
你好,有关javaocr的问题想请教下你。
打开你的项目,运行 ...
一个纯java的验证码识别算法
3.3. Thread Confinement(线程局限)
Accessing shared, mutable data requires using synchronization; one way to avoid this requirement is to not share. If data is only accessed from a single thread, no synchronization is needed. This technique, thread confinement, is one of the simplest ways to achieve thread safety. When an object is confined to a thread, such usage is automatically thread-safe even if the confined object itself is not [CPJ 2.3.2].
访问共享的、可变的数据需要用到同步机制。一种可以避免这种同步需求的方式是避免这种共享。如果数据只能被单线程的访问,那么同步机制就不需要了。线程局限技术就是这种简单的实现线程安全的技术。当一个对象被局限在一个线程内部使用的时候,尽管该对象本身可能不是线程安全的,但是这种用法可以实现线程安全。
Swing uses thread confinement extensively. The Swing visual components and data model objects are not thread safe; instead, safety is achieved by confining them to the Swing event dispatch thread. To use Swing properly, code running in threads other than the event thread should not access these objects. (To make this easier, Swing provides the invokeLater mechanism to schedule a Runnable for execution in the event thread.) Many concurrency errors in Swing applications stem from improper use of these confined objects from another thread.
Swing框架广泛的使用了线程局限技术。Swing框架的图形组件以及数据模型对象都不是线程安全的。线程安全性是通过把这些对象局限在Swing时间分发线程中来做到的。想要恰当的使用Swing框架的话,不是事件的线程不应该访问到这些对象(为了做到使用简单,Swing框架提供了invokeLater机制来调度事件线程中执行的Runnable对象)。很多Swing应用程序中的并发错误都可能是由其他线程对局限对象的不正确使用引起的。
Another common application of thread confinement is the use of pooled JDBC (Java Database Connectivity) Connection objects. The JDBC specification does not require that Connection objects be thread-safe.[9] In typical server applications, a thread acquires a connection from the pool, uses it for processing a single request, and returns it. Since most requests, such as servlet requests or EJB (Enterprise JavaBeans) calls, are processed synchronously by a single thread, and the pool will not dispense the same connection to another thread until it has been returned, this pattern of connection management implicitly confines the Connection to that thread for the duration of the request.
[9] The connection pool implementations provided by application servers are thread-safe; connection pools are necessarily accessed from multiple threads, so a non-thread-safe implementation would not make sense.
另外一个线程局限技术的常见应用是池化的JDBC连接对象。JDBC规范中并没有要求连接对象是线程安全的。在典型的服务器应用程序中,一个线程可能会从池中请求获取一个连接,使用该连接处理一个单独的请求,然后将该连接对象放回池中。由于大多数请求,例如servlet请求和EJB请求,都是在一个单独的线程中同步的运行的。在某一个线程被释放之前,线程池不会将该线程分配给其他链接。这种连接管理方式隐式的在请求的处理过程中,将连接局限在一个线程之内。
由应用服务器提供的连接池的实现是线程安全的,由于连接池需要在多线程的环境下被使用,因此如果实现不是线程安全的,则该实现没有任何意义。
Just as the language has no mechanism for enforcing that a variable is guarded by a lock, it has no means of confining an object to a thread. Thread confinement is an element of your program's design that must be enforced by its implementation. The language and core libraries provide mechanisms that can help in maintaining thread confinement local variables and the ThreadLocal class but even with these, it is still the programmer's responsibility to ensure that thread-confined objects do not escape from their intended thread.
就像Java语言本身没有为每一个变量都加上锁机制一样,Java语言也没有提供将一个对象局限在一个线程内的方法。因此,线程局限是你在程序设计时候的一个概念,这种概念取决于你的实现。虽然语言和核心类库提供可能保持线程局限性的本体类库和ThreadLocal类,但即便如此,保证线程局限的对象不会从他所在的线程中逃逸仍然是程序员的责任。
3.3.1. Ad-hoc Thread Confinement(非正式线程局限)
Ad-hoc thread confinement describes when the responsibility for maintaining thread confinement falls entirely on the implementation. Ad-hoc thread confinement can be fragile because none of the language features, such as visibility modifiers or local variables, helps confine the object to the target thread. In fact, references to thread-confined objects such as visual components or data models in GUI applications are often held in public fields.
Ad-hoc线程安全局限描述了维护线程局限的责任整个落在实现的时刻。由于没有利用任何的语言特性例如可见性修饰符或者本地变量,Ad-hoc线程局限可能是非常脆弱的。事实上,对于线程局限对象的应用(例如图形组件或者GUI应用中的数据模型)通常都是在public域中保持的。
The decision to use thread confinement is often a consequence of the decision to implement a particular subsystem, such as the GUI, as a single-threaded subsystem. Single-threaded subsystems can sometimes offer a simplicity benefit that outweighs the fragility of ad-hoc thread confinement.[10]
[10] Another reason to make a subsystem single-threaded is deadlock avoidance; this is one of the primary reasons most GUI frameworks are single-threaded. Single-threaded subsystems are covered in Chapter 9.
决定使用线程局限技术通常是想要将一个特定的子系统(例如GUI)实现成单线程子系统的结果。有时候单线程子系统提供的简单性有时候可以压过由于特别的线程局限所带来的脆弱性。另外一个经常要将子系统单线程化的原因是死锁的避免。这是大多数的GUI框架都是单线程的主要原因之一。单线程子系统将会在第九章进行讨论。
A special case of thread confinement applies to volatile variables. It is safe to perform read-modify-write operations on shared volatile variables as long as you ensure that the volatile variable is only written from a single thread. In this case, you are confining the modification to a single thread to prevent race conditions, and the visibility guarantees for volatile variables ensure that other threads see the most up-to-date value.
一个特别的线程局限的例子是volatile类型变量。只要你能够保证对volatile类型变量的修改是在单线程中完成的,那么对于共享volatile类型变量的read-modify-write操作就是安全的。在这个例子中,实际上就是采用将修改局限在单线程中来防止条件竞争的。Volatile类型的可见性保证可以确保其他线程看到最新的值。
Because of its fragility, ad-hoc thread confinement should be used sparingly; if possible, use one of the stronger forms of thread confinment (stack confinement or ThreadLocal) instead.
由于ad-hoc线程局限的脆弱性,应该限制该技术的使用。如果可能,应该使用形式更强的局限化技术来取代该技术。
3.3.2. Stack Confinement(栈局限)
Stack confinement is a special case of thread confinement in which an object can only be reached through local variables. Just as encapsulation can make it easier to preserve invariants, local variables can make it easier to confine objects to a thread. Local variables are intrinsically confined to the executing thread; they exist on the executing thread's stack, which is not accessible to other threads. Stack confinement (also called within-thread or thread-local usage, but not to be confused with the THReadLocal library class) is simpler to maintain and less fragile than ad-hoc thread confinement.
栈局限是一种线程局限的特殊形式,这种局限方式使得只能通过本地变量才能访问某个对象。如同封装能够很容易地维护不变性,本地变量可以方便地将一个对象局限在一个线程中。本地变量从本质上就是被局限在正在执行的线程之中。他们存在于执行线程的栈中,他们无法被其他线程访问。栈局限(也被称为线程内或者本地线程用法,不要与ThreadLocal混淆)比起ad-hoc线程局限更容易被维护并且更加强壮。
For primitively typed local variables, such as numPairs in loadTheArk in Listing 3.9, you cannot violate stack confinement even if you tried. There is no way to obtain a reference to a primitive variable, so the language semantics ensure that primitive local variables are always stack confined.
对于简单类型的本地变量,例如Listing类中的numPairs,无论如何你都不会违法栈局限。由于Java语言无法提供一个对简单类型变量的应用,因此语法本身就可以保证简单类型的本地变量永远是栈局限的。
Listing 3.9. Thread Confinement of Local Primitive and Reference Variables.
public int loadTheArk(Collection<Animal> candidates) {
SortedSet<Animal> animals;
int numPairs = 0;
Animal candidate = null;
// animals confined to method, don't let them escape!
animals = new TreeSet<Animal>(new SpeciesGenderComparator());
animals.addAll(candidates);
for (Animal a : animals) {
if (candidate == null || !candidate.isPotentialMate(a))
candidate = a;
else {
ark.load(new AnimalPair(candidate, a));
++numPairs;
candidate = null;
}
}
return numPairs;
}
Maintaining stack confinement for object references requires a little more assistance from the programmer to ensure that the referent does not escape. In loadTheArk, we instantiate a treeSet and store a reference to it in animals. At this point, there is exactly one reference to the Set, held in a local variable and therefore confined to the executing thread. However, if we were to publish a reference to the Set (or any of its internals), the confinement would be violated and the animals would escape.
要保持对象的应用的栈局限性需要程序员的更多的主动性来防止引用的逃逸。在loadTheArk方法中,我们实例化一个TreeSet对象,然后使用Animas引用该对象。此刻,只有该TreeSet只有一个应用,而且该应用是本地变量,这样栈局限就完成了。但是如果我们公开了对该Set的应用的话,局限就会被破坏,“动物”就会逃窜出来。
Using a non-thread-safe object in a within-thread context is still thread-safe. However, be careful: the design requirement that the object be confined to the executing thread, or the awareness that the confined object is not thread-safe, often exists only in the head of the developer when the code is written. If the assumption of within-thread usage is not clearly documented, future maintainers might mistakenly allow the object to escape.
将一个非线程安全的对象应用在一个单线程的上下文环境中仍然是线程安全的。但是,请注意:这种设计需求要求对象被局限在正在执行的线程中,或者注意被局限的对象并不是线程安全的,这通常只会在代码被编写的时候停留在程序员的脑海中。如果这种限制并没有被很好的文档化,那该类很可能会被后来的使用者误用。
3.3.3. ThreadLocal
A more formal means of maintaining thread confinement is ThreadLocal, which allows you to associate a per-thread value with a value-holding object. Thread-Local provides get and set accessor methods that maintain a separate copy of the value for each thread that uses it, so a get returns the most recent value passed to set from the currently executing thread.
一个更加形式良好的维护线程局限的工具是ThreadLocal,该类可以允许你将表示某个线程的值与一个保存值的对象相关联。Thread-Local提供了get和set的访问符来为每个使用他的线程来保存独立的对象拷贝,get方法可以为正在执行的线程返回使用set方法最近修改的值。
Thread-local variables are often used to prevent sharing in designs based on mutable Singletons or global variables. For example, a single-threaded application might maintain a global database connection that is initialized at startup to avoid having to pass a Connection to every method. Since JDBC connections may not be thread-safe, a multithreaded application that uses a global connection without additional coordination is not thread-safe either. By using a ThreadLocal to store the JDBC connection, as in ConnectionHolder in Listing 3.10, each thread will have its own connection.
Thread-local变量通常用来阻止基于可变的单态或者全局变量的共享。例如,单线程的应用程序可能会在初始化的时候保存一个全局的数据库连接,这样就可以避免将该连接对象传递给每一个方法。由于JDBC连接并不是线程安全的,多线程的应用程序在没有额外控制的情况下使用全局的连接就不是线程安全的。通过使用ThreadLocal类来保存JDBC连接,这样每个线程都会拥有自己的数据库连接。
Listing 3.10. Using ThreadLocal to Ensure thread Confinement.
private static ThreadLocal<Connection> connectionHolder
= new ThreadLocal<Connection>() {
public Connection initialValue() {
return DriverManager.getConnection(DB_URL);
}
};
public static Connection getConnection() {
return connectionHolder.get();
}
This technique can also be used when a frequently used operation requires a temporary object such as a buffer and wants to avoid reallocating the temporary object on each invocation. For example, before Java 5.0, Integer.toString used a ThreadLocal to store the 12-byte buffer used for formatting its result, rather than using a shared static buffer (which would require locking) or allocating a new buffer for each invocation.[11]
[11] This technique is unlikely to be a performance win unless the operation is performed very frequently or the allocation is unusually expensive. In Java 5.0, it was replaced with the more straightforward approach of allocating a new buffer for every invocation, suggesting that for something as mundane as a temporary buffer, it is not a performance win.
当需要频繁的使用一个诸如buffer这样的临时对象并且希望避免每次调用的时候都重新分配该对象的时候,这项技术同样也可以用于解决这样的问题。例如,在Java5.0之前,Integer.toString()使用ThreadLocal来保存一个12比特的buffer来格式化输出结果,而不是使用一个全局的buffer(这样做需要用到锁机制)也不是为每次调用都分配一个新的buffer。这项技术本身并不太可能会带来操作性能的提供,除非对象的分配特别频繁,或者分配的代价非常高。在Java5.0中,这种方式被一种更为直接的方法取代-为每次调用分配一个新的buffer。对于一个非常像uffer这样临时变量,这种做法并不会带来性能的提升。
When a thread calls ThreadLocal.get for the first time, initialValue is consulted to provide the initial value for that thread. Conceptually, you can think of a ThreadLocal<T> as holding a Map<Thread,T> that stores the thread-specific values, though this is not how it is actually implemented. The thread-specific values are stored in the Thread object itself; when the thread terminates, the thread-specific values can be garbage collected.
当线程第一次访问ThreadLocal.get方法的时候,initialValue方法将会为该线程提供一个初始化的值。你可以将ThreadLocal<T>想象成在其内部有一个使用Map<Thead,T>来为其保存于线程有关的值,不过这不是ThreadLocal的实际实现。线程相关的值是被保存在线程对象的内部。当线程终止的时候,线程的相关值会被垃圾回收器回收。
If you are porting a single-threaded application to a multithreaded environment, you can preserve thread safety by converting shared global variables into ThreadLocals, if the semantics of the shared globals permits this; an application wide cache would not be as useful if it were turned into a number of thread-local caches.
如果你想要将一个单线程的应用程序移植到多线程环境中,在全局共享的语义允许的情况下,你可以通过将共享的全局变量保存在ThreadLocal中的方法来维护线程安全。如果被变成多个thread-local的缓存,那么应用范围内的缓存将不再有用。
ThreadLocal is widely used in implementing application frameworks. For example, J2EE containers associate a transaction context with an executing thread for the duration of an EJB call. This is easily implemented using a static Thread-Local holding the transaction context: when framework code needs to determine what transaction is currently running, it fetches the transaction context from this ThreadLocal. This is convenient in that it reduces the need to pass execution context information into every method, but couples any code that uses this mechanism to the framework.
在应用框架的实现中,ThreadLocal被广泛的应用。例如,J2EE容器在一个EJB调用的执行期间,会将一个事物的上下文环境与一个正在执行的线程相关联。使用一个静态的ThreadLocal来保存事物的上下文环境是非常简单的:当框架代码需要判断当前正在运行的是哪个事物的时候,它只需要从ThreadLocal中取得事物的上下文环境即可。这样就避免将上下文环境传递给每一个方法,与之相伴的是框架与代码的耦合。
It is easy to abuse ThreadLocal by treating its thread confinement property as a license to use global variables or as a means of creating "hidden" method arguments. Like global variables, thread-local variables can detract from reusability and introduce hidden couplings among classes, and should therefore be used with care.
ThreadLocal类很容易被滥用。比如使用其线程局限的属性作为一个使用全局变量的依据,或者作为一个为方法创建隐藏参数的方法。与global变量一样,ThreadLocal变量会带来复用性的降低以及类之间的隐性耦合,因此应该慎用。
Accessing shared, mutable data requires using synchronization; one way to avoid this requirement is to not share. If data is only accessed from a single thread, no synchronization is needed. This technique, thread confinement, is one of the simplest ways to achieve thread safety. When an object is confined to a thread, such usage is automatically thread-safe even if the confined object itself is not [CPJ 2.3.2].
访问共享的、可变的数据需要用到同步机制。一种可以避免这种同步需求的方式是避免这种共享。如果数据只能被单线程的访问,那么同步机制就不需要了。线程局限技术就是这种简单的实现线程安全的技术。当一个对象被局限在一个线程内部使用的时候,尽管该对象本身可能不是线程安全的,但是这种用法可以实现线程安全。
Swing uses thread confinement extensively. The Swing visual components and data model objects are not thread safe; instead, safety is achieved by confining them to the Swing event dispatch thread. To use Swing properly, code running in threads other than the event thread should not access these objects. (To make this easier, Swing provides the invokeLater mechanism to schedule a Runnable for execution in the event thread.) Many concurrency errors in Swing applications stem from improper use of these confined objects from another thread.
Swing框架广泛的使用了线程局限技术。Swing框架的图形组件以及数据模型对象都不是线程安全的。线程安全性是通过把这些对象局限在Swing时间分发线程中来做到的。想要恰当的使用Swing框架的话,不是事件的线程不应该访问到这些对象(为了做到使用简单,Swing框架提供了invokeLater机制来调度事件线程中执行的Runnable对象)。很多Swing应用程序中的并发错误都可能是由其他线程对局限对象的不正确使用引起的。
Another common application of thread confinement is the use of pooled JDBC (Java Database Connectivity) Connection objects. The JDBC specification does not require that Connection objects be thread-safe.[9] In typical server applications, a thread acquires a connection from the pool, uses it for processing a single request, and returns it. Since most requests, such as servlet requests or EJB (Enterprise JavaBeans) calls, are processed synchronously by a single thread, and the pool will not dispense the same connection to another thread until it has been returned, this pattern of connection management implicitly confines the Connection to that thread for the duration of the request.
[9] The connection pool implementations provided by application servers are thread-safe; connection pools are necessarily accessed from multiple threads, so a non-thread-safe implementation would not make sense.
另外一个线程局限技术的常见应用是池化的JDBC连接对象。JDBC规范中并没有要求连接对象是线程安全的。在典型的服务器应用程序中,一个线程可能会从池中请求获取一个连接,使用该连接处理一个单独的请求,然后将该连接对象放回池中。由于大多数请求,例如servlet请求和EJB请求,都是在一个单独的线程中同步的运行的。在某一个线程被释放之前,线程池不会将该线程分配给其他链接。这种连接管理方式隐式的在请求的处理过程中,将连接局限在一个线程之内。
由应用服务器提供的连接池的实现是线程安全的,由于连接池需要在多线程的环境下被使用,因此如果实现不是线程安全的,则该实现没有任何意义。
Just as the language has no mechanism for enforcing that a variable is guarded by a lock, it has no means of confining an object to a thread. Thread confinement is an element of your program's design that must be enforced by its implementation. The language and core libraries provide mechanisms that can help in maintaining thread confinement local variables and the ThreadLocal class but even with these, it is still the programmer's responsibility to ensure that thread-confined objects do not escape from their intended thread.
就像Java语言本身没有为每一个变量都加上锁机制一样,Java语言也没有提供将一个对象局限在一个线程内的方法。因此,线程局限是你在程序设计时候的一个概念,这种概念取决于你的实现。虽然语言和核心类库提供可能保持线程局限性的本体类库和ThreadLocal类,但即便如此,保证线程局限的对象不会从他所在的线程中逃逸仍然是程序员的责任。
3.3.1. Ad-hoc Thread Confinement(非正式线程局限)
Ad-hoc thread confinement describes when the responsibility for maintaining thread confinement falls entirely on the implementation. Ad-hoc thread confinement can be fragile because none of the language features, such as visibility modifiers or local variables, helps confine the object to the target thread. In fact, references to thread-confined objects such as visual components or data models in GUI applications are often held in public fields.
Ad-hoc线程安全局限描述了维护线程局限的责任整个落在实现的时刻。由于没有利用任何的语言特性例如可见性修饰符或者本地变量,Ad-hoc线程局限可能是非常脆弱的。事实上,对于线程局限对象的应用(例如图形组件或者GUI应用中的数据模型)通常都是在public域中保持的。
The decision to use thread confinement is often a consequence of the decision to implement a particular subsystem, such as the GUI, as a single-threaded subsystem. Single-threaded subsystems can sometimes offer a simplicity benefit that outweighs the fragility of ad-hoc thread confinement.[10]
[10] Another reason to make a subsystem single-threaded is deadlock avoidance; this is one of the primary reasons most GUI frameworks are single-threaded. Single-threaded subsystems are covered in Chapter 9.
决定使用线程局限技术通常是想要将一个特定的子系统(例如GUI)实现成单线程子系统的结果。有时候单线程子系统提供的简单性有时候可以压过由于特别的线程局限所带来的脆弱性。另外一个经常要将子系统单线程化的原因是死锁的避免。这是大多数的GUI框架都是单线程的主要原因之一。单线程子系统将会在第九章进行讨论。
A special case of thread confinement applies to volatile variables. It is safe to perform read-modify-write operations on shared volatile variables as long as you ensure that the volatile variable is only written from a single thread. In this case, you are confining the modification to a single thread to prevent race conditions, and the visibility guarantees for volatile variables ensure that other threads see the most up-to-date value.
一个特别的线程局限的例子是volatile类型变量。只要你能够保证对volatile类型变量的修改是在单线程中完成的,那么对于共享volatile类型变量的read-modify-write操作就是安全的。在这个例子中,实际上就是采用将修改局限在单线程中来防止条件竞争的。Volatile类型的可见性保证可以确保其他线程看到最新的值。
Because of its fragility, ad-hoc thread confinement should be used sparingly; if possible, use one of the stronger forms of thread confinment (stack confinement or ThreadLocal) instead.
由于ad-hoc线程局限的脆弱性,应该限制该技术的使用。如果可能,应该使用形式更强的局限化技术来取代该技术。
3.3.2. Stack Confinement(栈局限)
Stack confinement is a special case of thread confinement in which an object can only be reached through local variables. Just as encapsulation can make it easier to preserve invariants, local variables can make it easier to confine objects to a thread. Local variables are intrinsically confined to the executing thread; they exist on the executing thread's stack, which is not accessible to other threads. Stack confinement (also called within-thread or thread-local usage, but not to be confused with the THReadLocal library class) is simpler to maintain and less fragile than ad-hoc thread confinement.
栈局限是一种线程局限的特殊形式,这种局限方式使得只能通过本地变量才能访问某个对象。如同封装能够很容易地维护不变性,本地变量可以方便地将一个对象局限在一个线程中。本地变量从本质上就是被局限在正在执行的线程之中。他们存在于执行线程的栈中,他们无法被其他线程访问。栈局限(也被称为线程内或者本地线程用法,不要与ThreadLocal混淆)比起ad-hoc线程局限更容易被维护并且更加强壮。
For primitively typed local variables, such as numPairs in loadTheArk in Listing 3.9, you cannot violate stack confinement even if you tried. There is no way to obtain a reference to a primitive variable, so the language semantics ensure that primitive local variables are always stack confined.
对于简单类型的本地变量,例如Listing类中的numPairs,无论如何你都不会违法栈局限。由于Java语言无法提供一个对简单类型变量的应用,因此语法本身就可以保证简单类型的本地变量永远是栈局限的。
Listing 3.9. Thread Confinement of Local Primitive and Reference Variables.
public int loadTheArk(Collection<Animal> candidates) {
SortedSet<Animal> animals;
int numPairs = 0;
Animal candidate = null;
// animals confined to method, don't let them escape!
animals = new TreeSet<Animal>(new SpeciesGenderComparator());
animals.addAll(candidates);
for (Animal a : animals) {
if (candidate == null || !candidate.isPotentialMate(a))
candidate = a;
else {
ark.load(new AnimalPair(candidate, a));
++numPairs;
candidate = null;
}
}
return numPairs;
}
Maintaining stack confinement for object references requires a little more assistance from the programmer to ensure that the referent does not escape. In loadTheArk, we instantiate a treeSet and store a reference to it in animals. At this point, there is exactly one reference to the Set, held in a local variable and therefore confined to the executing thread. However, if we were to publish a reference to the Set (or any of its internals), the confinement would be violated and the animals would escape.
要保持对象的应用的栈局限性需要程序员的更多的主动性来防止引用的逃逸。在loadTheArk方法中,我们实例化一个TreeSet对象,然后使用Animas引用该对象。此刻,只有该TreeSet只有一个应用,而且该应用是本地变量,这样栈局限就完成了。但是如果我们公开了对该Set的应用的话,局限就会被破坏,“动物”就会逃窜出来。
Using a non-thread-safe object in a within-thread context is still thread-safe. However, be careful: the design requirement that the object be confined to the executing thread, or the awareness that the confined object is not thread-safe, often exists only in the head of the developer when the code is written. If the assumption of within-thread usage is not clearly documented, future maintainers might mistakenly allow the object to escape.
将一个非线程安全的对象应用在一个单线程的上下文环境中仍然是线程安全的。但是,请注意:这种设计需求要求对象被局限在正在执行的线程中,或者注意被局限的对象并不是线程安全的,这通常只会在代码被编写的时候停留在程序员的脑海中。如果这种限制并没有被很好的文档化,那该类很可能会被后来的使用者误用。
3.3.3. ThreadLocal
A more formal means of maintaining thread confinement is ThreadLocal, which allows you to associate a per-thread value with a value-holding object. Thread-Local provides get and set accessor methods that maintain a separate copy of the value for each thread that uses it, so a get returns the most recent value passed to set from the currently executing thread.
一个更加形式良好的维护线程局限的工具是ThreadLocal,该类可以允许你将表示某个线程的值与一个保存值的对象相关联。Thread-Local提供了get和set的访问符来为每个使用他的线程来保存独立的对象拷贝,get方法可以为正在执行的线程返回使用set方法最近修改的值。
Thread-local variables are often used to prevent sharing in designs based on mutable Singletons or global variables. For example, a single-threaded application might maintain a global database connection that is initialized at startup to avoid having to pass a Connection to every method. Since JDBC connections may not be thread-safe, a multithreaded application that uses a global connection without additional coordination is not thread-safe either. By using a ThreadLocal to store the JDBC connection, as in ConnectionHolder in Listing 3.10, each thread will have its own connection.
Thread-local变量通常用来阻止基于可变的单态或者全局变量的共享。例如,单线程的应用程序可能会在初始化的时候保存一个全局的数据库连接,这样就可以避免将该连接对象传递给每一个方法。由于JDBC连接并不是线程安全的,多线程的应用程序在没有额外控制的情况下使用全局的连接就不是线程安全的。通过使用ThreadLocal类来保存JDBC连接,这样每个线程都会拥有自己的数据库连接。
Listing 3.10. Using ThreadLocal to Ensure thread Confinement.
private static ThreadLocal<Connection> connectionHolder
= new ThreadLocal<Connection>() {
public Connection initialValue() {
return DriverManager.getConnection(DB_URL);
}
};
public static Connection getConnection() {
return connectionHolder.get();
}
This technique can also be used when a frequently used operation requires a temporary object such as a buffer and wants to avoid reallocating the temporary object on each invocation. For example, before Java 5.0, Integer.toString used a ThreadLocal to store the 12-byte buffer used for formatting its result, rather than using a shared static buffer (which would require locking) or allocating a new buffer for each invocation.[11]
[11] This technique is unlikely to be a performance win unless the operation is performed very frequently or the allocation is unusually expensive. In Java 5.0, it was replaced with the more straightforward approach of allocating a new buffer for every invocation, suggesting that for something as mundane as a temporary buffer, it is not a performance win.
当需要频繁的使用一个诸如buffer这样的临时对象并且希望避免每次调用的时候都重新分配该对象的时候,这项技术同样也可以用于解决这样的问题。例如,在Java5.0之前,Integer.toString()使用ThreadLocal来保存一个12比特的buffer来格式化输出结果,而不是使用一个全局的buffer(这样做需要用到锁机制)也不是为每次调用都分配一个新的buffer。这项技术本身并不太可能会带来操作性能的提供,除非对象的分配特别频繁,或者分配的代价非常高。在Java5.0中,这种方式被一种更为直接的方法取代-为每次调用分配一个新的buffer。对于一个非常像uffer这样临时变量,这种做法并不会带来性能的提升。
When a thread calls ThreadLocal.get for the first time, initialValue is consulted to provide the initial value for that thread. Conceptually, you can think of a ThreadLocal<T> as holding a Map<Thread,T> that stores the thread-specific values, though this is not how it is actually implemented. The thread-specific values are stored in the Thread object itself; when the thread terminates, the thread-specific values can be garbage collected.
当线程第一次访问ThreadLocal.get方法的时候,initialValue方法将会为该线程提供一个初始化的值。你可以将ThreadLocal<T>想象成在其内部有一个使用Map<Thead,T>来为其保存于线程有关的值,不过这不是ThreadLocal的实际实现。线程相关的值是被保存在线程对象的内部。当线程终止的时候,线程的相关值会被垃圾回收器回收。
If you are porting a single-threaded application to a multithreaded environment, you can preserve thread safety by converting shared global variables into ThreadLocals, if the semantics of the shared globals permits this; an application wide cache would not be as useful if it were turned into a number of thread-local caches.
如果你想要将一个单线程的应用程序移植到多线程环境中,在全局共享的语义允许的情况下,你可以通过将共享的全局变量保存在ThreadLocal中的方法来维护线程安全。如果被变成多个thread-local的缓存,那么应用范围内的缓存将不再有用。
ThreadLocal is widely used in implementing application frameworks. For example, J2EE containers associate a transaction context with an executing thread for the duration of an EJB call. This is easily implemented using a static Thread-Local holding the transaction context: when framework code needs to determine what transaction is currently running, it fetches the transaction context from this ThreadLocal. This is convenient in that it reduces the need to pass execution context information into every method, but couples any code that uses this mechanism to the framework.
在应用框架的实现中,ThreadLocal被广泛的应用。例如,J2EE容器在一个EJB调用的执行期间,会将一个事物的上下文环境与一个正在执行的线程相关联。使用一个静态的ThreadLocal来保存事物的上下文环境是非常简单的:当框架代码需要判断当前正在运行的是哪个事物的时候,它只需要从ThreadLocal中取得事物的上下文环境即可。这样就避免将上下文环境传递给每一个方法,与之相伴的是框架与代码的耦合。
It is easy to abuse ThreadLocal by treating its thread confinement property as a license to use global variables or as a means of creating "hidden" method arguments. Like global variables, thread-local variables can detract from reusability and introduce hidden couplings among classes, and should therefore be used with care.
ThreadLocal类很容易被滥用。比如使用其线程局限的属性作为一个使用全局变量的依据,或者作为一个为方法创建隐藏参数的方法。与global变量一样,ThreadLocal变量会带来复用性的降低以及类之间的隐性耦合,因此应该慎用。
发表评论
-
使用commons-fileupload实现单个和多个文件上传
2013-06-24 16:19 913见如下: http://www.blogjava.net/s ... -
pgpool-I I的recovery
2013-06-06 19:51 945pgpool-I I のオンラインリカバリの概要 -
ウェブサーバの 暗号アルゴリズムの選び方
2013-03-26 10:59 975日语的一份关于ssl的加密算法的文档,有时间的话需要研究一下。 ... -
struts2 best practice-Why we need a framework.
2012-12-03 16:28 1018A web application framework is ... -
struts2 best practice-Use empty action components to forward to your results
2012-11-29 12:25 899Use empty action components to ... -
struts2中inceptor的执行顺序
2012-08-15 17:27 1034struts2中的inceptor是可以指定执行顺序的。 具 ... -
漫谈HTTPS(挖坑待填)
2012-04-23 09:13 1041漫谈HTTPS(挖坑待填) -
Java序列化之四: 进一步思考
2012-04-20 10:24 9761,当需要被序列化的类对象中的一部分成员变量是不可被序列化的, ... -
Java序列化之三: 常见实例分析
2012-04-20 10:20 15561,HTTPSession与Serializale ... -
Java序列化之二: 从代码开始
2012-04-19 14:20 12831,最简单,最典型的序列化代码。 附录1中给出的JAV ... -
Java序列化之一: 什么是JAVA序列化
2012-04-19 14:03 1969这几天受领导委托,做 ... -
一个纯java的验证码识别算法
2012-04-05 08:45 33293在进行性能测试时,某些时候需要输入验证码。手工输入是不可能的, ... -
連載二、Servlet 3.0の6つのEase of Development
2011-07-22 14:16 818Servlet 3.0では、EoDとして「Annotation ... -
連載一、Servlet 3.0の6つの主な変更点
2011-07-22 14:00 819Tomcat 7では、Tomcat 6に対して実装するサーブレ ... -
連載二、クロスサイトスクリプティング基本
2011-07-13 10:01 722XSSセキュリティホールによる起こり得る被害 ●cookie ... -
qmailによるSMTPサーバの構築
2011-06-15 14:41 12311、qmailの仕組み a、sendmailが、メッセー ... -
LDAP SCHEMA DESIGN(三)
2010-11-05 11:34 13353.2 Do not modify the standard ... -
LDAP SCHEMA DESIGN(二)
2010-11-04 09:42 12732 Requirements When considerin ... -
LDAP SCHEMA DESIGN_Synopsis (大纲)
2010-11-02 16:55 1490Synopsis (大纲) ... -
Chapter 4. Composing Objects(合成对象)
2010-01-13 11:02 1055Chapter 4. Composing Objects(组合 ...
相关推荐
在多线程环境下,对象的可见性(Visibility)、发布(Publication)和逃逸(Escape)、线程封闭(Thread Confinement)、不可变性(Immutability)以及安全发布(Safe Publication)是实现线程安全的关键概念。...
1. 夸克禁闭(Quark Confinement):在量子色动力学(Quantum Chromodynamics, QCD)的框架下,夸克是构成强子(如质子和中子)的基本粒子。夸克禁闭是指夸克永远无法被独立分离出来,只能以组合形式(如夸克-反夸克...
- 线程封闭(Thread Confinement):一种确保线程安全的策略,通常通过ThreadLocal等机制实现。 - 不可变对象(Immutable Objects):一旦创建就不能被修改的对象,天然线程安全。 学习Java并发编程,重点在于理解...
- `java.lang.Thread`是Java中最基本的线程类,用于创建和管理线程。 - 学习如何实例化线程、启动线程以及管理线程生命周期是并发编程的基础。 2. **关键字`synchronized`和`volatile`** - `synchronized`关键字...
- **Multilayer Systems:** In multilayer systems, the presence of multiple interfaces can lead to complex behaviors, including the excitation of guided modes and enhanced confinement effects. ...
Confinement is used to prohibit safety-critical objects from unintended access. Approaches for specifying and verifying confinement have been proposed in the last twenty years but their application ...
In this Letter, blue phosphorescence organic light-emitting diodes (PHOLEDs) employ structures for electron and/or hole confinement; 1,3,5-tris(N-phenylbenzimiazole-2-yl)benzene is used as a hole ...
A new configuration of the confinement structure is utilized to improve optoelectronic performance, including threshold current, ac current gain, optical bandwidth, and optical output power of a ...
纳米CdS and CdSe 发光蓝移:量子限域或量子测不准?,孙长庆,S. LI,Blue shift of semconductor nanosolids is shown arise from surface bond contraction rather than
标题“plasma_confinement”涉及的是等离子体约束技术,这是核聚变研究中的一个核心领域。等离子体是物质的第四态,由高度电离的原子组成,具有独特的电磁性质。在核聚变反应中,高温高能的等离子体需要被有效地约束...
checking, error signalling and fault confinement. Within the transfer layer it is decided whether the bus is free for starting a new transmission or whether a reception is just starting. Also some ...
"cow-confinement:CERC2015解决的问题"是一个基于2015年中欧区域竞赛中的实际问题,该问题关注的是优化牛圈养的策略。在这个问题中,参赛者可能面临如何在有限的空间内有效地安排母牛的饲养,以最大化效益或满足特定...
checking, error signalling and fault confinement. Within the transfer layer it is decided whether the bus is free for starting a new transmission or whether a reception is just starting. Also some ...
One reason these factors have a large impact on the performance of inertial confinement fusion implosions is the high convergence required to achieve high fusion gains. To tackle these problems, a ...
A method for inertial confinement fusion driven by powerful long wavelength electromagnetic pulses (EMPs), such as
A unique approach for permeation filling of nonpermeable inertial confinement fusion target capsules with deuterium–tritium (DT) is presented. This process uses a permeable capsule coupled into the ...
Confinement loss in hollow-core negative curvature fiber: A multi-layered model