What is a thread-local variable (thread-local variable). Easy to use threads: do not share sometimes the best ThreadLocal classes are quietly appearing in version 1.2 of the Java platform. Although supporting thread-local variables has long been part of many threading tools, such as the Posix pthreads tool, the original design of the Java Threads API does not have this useful feature. Moreover, the initial implementation was rather inefficient. For these reasons, ThreadLocal is rarely noticed, but it is handy for simplifying the development of thread-safe concurrency programs. In the easy to use thread's 3rd part, Java Software Advisor Brian Goetz studied ThreadLocal and provided some tips for using it.
Participate in Brian's multithreaded Java programming discussion forum to get help with threading and concurrency issues in your project.
Writing thread-safe classes is difficult. It not only requires careful analysis of the conditions in which variables can be read and written, but also requires a careful analysis of how other classes can use a class. Sometimes it is difficult to make a class thread-safe without affecting the functionality, ease of use, or performance of the class. Some classes retain state information from one method call to the next method call, and it is difficult to make such a class thread-safe in practice.
It is easier to manage the use of non-thread-safe classes than to try to make the class thread-safe. Non-thread-safe classes are generally safe to use in multithreaded programs, as long as you can ensure that instances of the classes used by one thread are not used by other threads. For example, the JDBC Connection class is not thread-safe-two threads cannot securely share a connection-on a small granularity level but if each thread has its own Connection, then multiple threads can safely perform database operations at the same time.
It is certainly possible to maintain a separate JDBC connection (or any other object) for each thread without using ThreadLocal; the thread API gives us all the tools we need to connect objects and threads. ThreadLocal makes it easier for us to relate the thread to its per-thread (per-thread) data successfully.
What is a thread-local variable (thread-local variable).
A thread-local variable efficiently provides a copy of a separate thread-local variable value for each thread that uses it. Each thread sees only the values associated with itself, not knowing that other threads may be using or modifying their own replicas. Some compilers, such as the Microsoft Visual C + + compiler or the IBM XL FORTRAN compiler, integrate support for thread-local variables into their language with storage category modifiers such as static or volatile. The Java compiler does not provide special language support for thread-local variables; instead, it implements these support with the ThreadLocal class, which has special support for this class in the core thread class.
Because thread-local variables are implemented through a class, rather than as part of the Java language itself, the use syntax of Java-language thread-local variables is more awkward than the use syntax of the built-in thread-local variable language. To create a thread local variable, instantiate an object of the class ThreadLocal. The behavior of the ThreadLocal class is similar to the behavior of various Reference classes in Java.lang.ref; the ThreadLocal class acts as an indirect handle when storing or retrieving a value. Listing 1 shows the ThreadLocal interface.
Listing 1. ThreadLocal Interface
The
Get () accessor retrieves the value of the current thread of the variable, and the set () accessor modifies the value of the current thread. The InitialValue () method is optional, and if the thread has not used a variable, you can use this method to set the initial value of the variable, which allows for lazy initialization. The best way to illustrate how ThreadLocal works is by using an example implementation. Listing 2 shows a way to implement ThreadLocal. It is not a particularly good implementation (although it is very similar to the initial implementation), so it is likely to be poor performance, but it clearly illustrates how ThreadLocal works.
Listing 2. ThreadLocal's bad implementation
This implementation does not perform well because each get () and set () operation requires synchronization on the values map, and contention occurs if multiple threads simultaneously access the same ThreadLocal. In addition, this implementation is impractical because using the thread object to do the keyword in the Values mapping table will cause the thread to be garbage collected after the thread has exited, and the thread-specific value of the ThreadLocal of the dead thread cannot be garbage collected.
Implement per-thread Singleton with ThreadLocal
Thread-local variables are often used to depict stateful "Singleton" or thread-safe shared objects, either by encapsulating an entire variable that is unsafe into ThreadLocal, or by encapsulating the thread-specific state of an object into ThreadLocal. For example, in an application that has a close connection with a database, many methods of the program may require access to the database. It is inconvenient to include a Connection as a parameter in each method of the system-access to the connection with a "list" may be a more crude, but much more convenient technique. However, multiple threads cannot safely share a JDBC Connection. As shown in Listing 3, by using the ThreadLocal in the "list", we can make it easy for any class in our program to get a reference to Connection per thread. In this way, we can assume that ThreadLocal allows us to create per-thread lists.
Listing 3. Store a JDBC connection in a per-thread Singleton
Any State or non thread-safe object, such as JDBC Connection or regular expression matching, that is created more expensive than the cost of using it, is a good place to use each line of Cheng (singleton) technology. Of course, in places like this, you can use other technologies, such as pooling, to securely manage shared access. However, in terms of scalability, there are potential pitfalls even with pools. Because the pool implementation must use synchronization to maintain the integrity of the pool data structure, if all threads use the same pool, program performance will be reduced for contention in systems with many threads accessing the pool frequently.
|
Back to the top of the page |
|
Simplifying debug logging with ThreadLocal
Other applications that are suitable for use with ThreadLocal but not as a good alternative technology include storing or accumulating per-thread context information for later retrieval. For example, suppose you want to create a tool for managing debugging information for multithreaded applications. You can accumulate debugging information as a thread-local container using the Debuglogger class as shown in Listing 4. At the beginning of a unit of work, you empty the container, and when an error occurs, you query the container to retrieve all the debugging information generated by the work unit so far.
Listing 4. Manage per-thread debug logs with ThreadLocal
In your code, you can call Debuglogger.put () to save information about what your program is doing, and, later, if necessary (for example, an error has occurred), you can easily retrieve the debug information associated with a particular thread. This technique is much simpler and more effective than simply dumping all the information into a log file and then trying to figure out which log records come from which thread (and also worry about thread contention logging objects).
ThreadLocal is also useful in any multithreaded application server where a servlet-based application or work unit is a whole request, because a single thread is used throughout the process of processing a request. You can use the ThreadLocal variable to store various per-request (Per-request) contextual information using the per-thread-list technique described earlier.
|
Back to the top of the page |
|
ThreadLocal thread security Slightly worse cousins, inheritablethreadlocal
The ThreadLocal class has a relative, inheritablethreadlocal, which works in a similar way, but applies to a completely different kind of application. If you save the values of all Inheritablethreadlocal objects when you create a thread, those values are also automatically passed to the child thread. If a child thread calls inheritablethreadlocal get (), it will see the same object as its parent thread. To protect thread security, you should use inheritablethreadlocal only for immutable objects (objects that, once created, will never be changed), because objects are shared by multiple threads. Inheritablethreadlocal is suitable for Cheng data from a parent line to a child thread, such as a user ID or a transaction identity (transaction ID), but not a stateful object, such as JDBC Connection.
|
Back to the top of the page |
|
Performance of ThreadLocal
Although thread-local variables have long been known and supported by many thread frameworks including the Posix pthreads specification, they were omitted from the original Java thread design and added only in version 1.2 of the Java platform. In many ways, ThreadLocal is still evolving; it has been rewritten in version 1.3, rewritten in version 1.4, and both are specifically for performance issues.
In JDK 1.2, ThreadLocal is implemented in much the same way as in Listing 2, in addition to using synchronous Weakhashmap instead of HashMap to store values. (at the expense of some additional performance overhead, using Weakhashmap solves the problem of not being able to garbage collect the Thread object.) Needless to say, the performance of ThreadLocal is rather poor.
The ThreadLocal version provided by the Java Platform version 1.3 is as good as possible; it does not use any synchronization, so there is no scalability problem and it does not use weak references. Instead, people modify the thread class to support ThreadLocal by adding an instance variable to the thread that holds the current thread's mapping from the thread local variable to its value HashMap. Because the process of retrieving or setting a thread local variable does not involve reading or writing to data that may be read or written by another thread, you can implement Threadlocal.get () and set () without any synchronization. Also, because a reference to each thread value is stored in its own thread object, each thread value of the thread can also be garbage collected when the thread is garbage collected.
Unfortunately, even with these improvements, the performance of ThreadLocal in Java 1.3 is still surprisingly slow. According to my rough measurements, the threadlocal.get () operation in the Sun 1.3 JDK on a dual-processor Linux system takes about twice times the amount of contention-free synchronization. The reason for this poor performance is that the Thread.CurrentThread () method is expensive and accounts for more than Two-thirds of the Threadlocal.get () run time. Despite these drawbacks, JDK 1.3 threadlocal.get () is still much faster than contention synchronization, so if there is any serious contention (there may be a very large number of threads, or the synchronized block is frequently executed, or the sync block is big), ThreadLocal May still be much more efficient.
In the latest version of the Java platform, version 1.4b2, the performance of ThreadLocal and Thread.CurrentThread () has been greatly improved. With these improvements, ThreadLocal should be faster than other technologies, such as using pools. Because it is simpler and less error-prone than other technologies, people will eventually find it an effective way to avoid unnecessary interactions between threads.
|
Back to the top of the page |
|
The benefits of ThreadLocal
ThreadLocal can bring a lot of benefits. It is often the easiest way to portray stateful classes as thread-safe, or to encapsulate non thread-safe classes so that they can be used securely in a multithreaded environment. Using ThreadLocal allows us to bypass the complex process of determining when synchronization is necessary for thread safety, and because it does not require any synchronization, it also improves scalability. In addition to simplicity, storing each thread list or per-thread context information with ThreadLocal has a valuable benefit in archiving-by using ThreadLocal, objects stored in ThreadLocal are not shared by threads are clear, This simplifies the task of determining whether a class is thread safe.
I hope you have fun and knowledge in this series, and I encourage you to go into my discussion forums to delve into multithreaded issues. Posted @ 2007-04-09 20:52 sing reading (35) | Comments (0) | Editing the thread-safety issues in the Web server development environment
The servlet is in a multithreaded environment. That is, multiple requests may be sent to a Servelt instance, and each request is a thread.
The action under struts is similar, too, in a multithreaded environment. You can refer to the action Class in the struts user guide:http://struts.apache.org/struts-action/userguide/building_controller.html Design Guidelines section: Write code for a multi-threaded Environment-our controller servlet creates only one instance R Action class, and uses this one instance to service all requests. Thus, you are need to write Thread-safe Action classes. Follow the same guidelines you would use to write Thread-safe servlets.
Write code for multithreaded environments. Our controller servlet command creates an instance of your action class that uses this instance to service all requests. Therefore, you must write the thread-safe action class. Follow the same guidelines as the write-thread-safe servlet.
1. What is thread-safe code
Code that executes correctly in a multithreaded environment is thread-safe.
The meaning of security is to be able to execute correctly, otherwise the result is program execution error, may appear various unusual situation.
2. How to write thread-safe code
Many books explain how this is a problem, and they mainly explain how to synchronize the thread's use of shared resources. It is mainly about the various usages of the synchronized keyword, as well as the concept of lock.
Tool classes such as read and write locks are also available in the Java1.5. These require a high level of skill and are relatively difficult to debug.
However, thread synchronization is a method that is not possible, is more complex, and can result in a loss of performance. In the equivalent code, there is no need for synchronization to be much better at writing ease and performance.
What I'm emphasizing here is that the code is always thread-safe and does not need to be synchronized. As follows:
1 constants are always thread-safe because only read operations exist.
2 access to the constructor (new operation) is thread-safe because each time a new instance is created, the shared resource is not accessed.
3 The most important thing is that the local variable is thread safe. Because each method is executed, local variables are created in a separate space, which is not a shared resource. A local variable includes a parameter variable for the method.
The Struts User Guide has:
Only with local variables-the most important principle that aids in Thread-safe coding be to-use only local Variables, no T instance variables, in your Action class.
Use local variables only. The most important principle of writing thread-safe code is to use only local variables in the action class and not use instance variables.
Summarize:
Developed in a Java Web server environment, pay attention to thread safety issues. The simplest way to do this is to not use class variables, instance variables in the servlet and struts action, but you can use class constants and instance constants.
If you have these variables, you can convert them into parameter passes to the method to eliminate them.
Note A confusing place: whether an instance variable can be safely used in a class called by a servlet or action (such as a value object, a domain model class). If you do this every time the method is invoked,
When you create a new object and then call their methods, there is no synchronization problem---because they are not resources shared by multiple threads, only shared resources need to be synchronized---and instances of the servlet and action are shared by multiple threads.
In other words, instances of the servlet and action are invoked by multiple threads at the same time, and it is thread-safe to go through this layer, if there is no additional boot thread in your own code, and each time a subsequent business object is called to create a new instance and then invoke it. Posted @ 2007-04-09 20:31 sing reading (15) | Comments (0) | Edit Collection April 6, 2007 Actionservlet in-depth discussion java.lang.Object
|
+--javax.servlet.genericservlet
|
+--javax.servlet.http.httpservlet
|
+--org.apache.struts.action.actionservlet
Struts provides a default version of the Actionservlet class, and you can inherit this class, overwriting some of these methods to achieve your special processing needs. Actionservlet inheritance and Javax.servlet.http.HttpServlet, so in essence it's no different from a normal servlet, you can think of it as a servlet, just a different function. Actionservlet mainly completes the following functions:
Maps a URI from the client to a corresponding action class
If this action class is invoked for the first time, then instantiate one and put it in the cache
If the corresponding actionform is specified in the configuration file (Struts-config.xml), crawl the data population from the request Formbean
Invokes the Perform () method of the action class, passing in a reference to the actionmapping, corresponding Actionform, and httpservletrequest by the container to Actionservlet, HttpServletResponse object.
The correct version of the Actionservlet will read the following initialization parameters from the configuration file Web.xml:
Application
Base class for the resource bundle (resources bundle) that the application uses
Factory
The class name of the messageresourcesfactory used to create the applied Messageresources object. Indeed, the province is org.apache.struts.util.PropertyMessageResourcesFactory.
Config
Struts configuration file, the province is/web-inf/struts-config.xml. Note that this is the relative path associated with the application context.
Content
Defines the content type and encoding format of the exact province, which is automatically set to each response if there is no explicit setting in the Jsp/servlet. Indeed, the province is text/html.
Debug
Level of debugging information. The default is 0, and the debug information that is higher than the current level is logged to the log file.
Detail
Similar to the function of debug, except that this detail is initmapping (). Debug information is printed to System.out instead of log files.
Formbean
Actionformbean of the implementation of the class, the province is Org.apache.struts.action.ActionFormBean
Forward
Used in the application of the Actionforward class, the province is Org.apache.struts.action.ActionForward.
Locale
Specifies the locale object that is used in the province. Set to True, when a session is received, a Action.locale_key-marked LOCALE object is automatically stored in the sessions, if there are no LOCALE objects bound to Action.locale_key in the session.
Mapping
Used in the application of the Actionmapping class, the province is org.apache.struts.action.ActionMapping.
Multipartclass
File upload using the Mutipartrequesthandler implementation class. The Org.apache.struts.upload.DiskMultipartRequestHandler of the province
NoCache
If set to True, Actionservlet automatically adds NoCache HTML headers to each response to the client so that the client does not cache the pages in the application. True to False
Null
If set to True, the application returns NULL when an undefined message resource is obtained, instead of returning an error. It is true that the province is accurate.
MaxFileSize
File upload size limit, do 250M
BufferSize
The size of the buffer when the file is uploaded is 4M
TempDir
Set up a temporary directory for uploading. Working directories are provided as attributes of a servlet environment (context).
Validate
Are we using the new configuration file format is true.
Validating
Verify that the configuration XML file is validated for validity. True to the province
The command design pattern is applied in Actionservlet.
When a servlet is generated by a container, the init () method is first invoked to initialize, and the corresponding method is invoked when an HTTP request is received, such as a GET request calling the Doget () method, and a POST request calling the Dopost () method. So first look at the Actionservlet init () method and you'll know why Actionservlet can do that.
Init ()
In its init () method, Actionservlet calls the following protected method to complete the initialization:
Initactions ()-You may also have this question: why struts can find a request URI corresponding to the action class. Here's the answer, Actionservlet. There is an actions property, the type is ORG.APACHE.STRUTS.UTIL.FASTHASHMAP, used to store the instantiated action class with the full name of the class as key. The first call to Init () is the Initactions () method, which simply clears all name-value pairs in the map.
synchronized(actions) {Actions.setfast (false); Actions.clear (); Actions.setfast (true); }
First, the actions are set to slow mode, at which point the access to the Fasthashmap is synchronized, then clears all existing name/value pairs in the actions and then sets the actions to fast. Since Fasthashmap is an extended class based on struts on JAVA.UTIL.HASHMAP, it is designed to accommodate multithreading, and the need for HASHMAP access is mostly read-only for special environments. It is known that JAVA.UTIL.HASHMAP is not thread safe, so hashmap is generally suitable for single threaded environments. Org.apache.struts.FastHashMap is inherited from Java.util.HashMap, which is generated by adding multithreaded support. In fast mode it works like this: reading is not thread-synchronized, cloning the current map first, and then doing the write on the clone to replace the original map with this modified clone version. So when will the actions class be added to this map? We have mentioned that struts is dynamically generating an instance of an action class, and that every time Actionservlet receives a GET or post HTTP request, it looks for an instance of the corresponding action class in the map, and if it does not, instantiate one, and put it in the map. This action property is visible to the cache of action class instances.
Initinternal ()-initializes the resource bundle messageresources used within the Actionservlet, using Messageresources.getmessageresources (internalName) to get InternalName is the actionresources.properties file corresponding to "Org.apache.struts.action.ActionResources". This resource bundle is used primarily for actionservlet information used during processing, and is not discussed here.
Initdebug ()-Reads the debug-level parameter Getservletconfig (). Getinitparameter ("Debug") of this application from Web.xml and assigns it to the Debug property.
InitApplication ()-Initializes the application resource bundle and places it into the ServletContext.
StringFactory =getservletconfig (). Getinitparameter ("Factory");StringOldfacory = Messageresourcesfactory.getfactoryclass ();if(Factory!=NULL) Messageresourcesfactory.setfactoryclass (Factory);StringValue = Getservletconfig (). Getinitparameter ("Application"); Messageresourcesfactory factoryobject = Messageresourcesfactory.createfactory (); Application = factoryobject.createresources (value); Messageresourcesfactory.setfactory (oldfactory); Getservletcontext (). setattribute (Action.messages_key, application);
Note: The code snippet referenced in this article may omit some of the main content, such as exception check, please note.
The factory parameter is read first from the configuration file, and if this argument is not empty, the specified factory class is used in the messageresourcesfactory; Use the default factory class Org.apche.struts.util.PropertyMessageResourceFactory. Then call the Messageresourcesfactory static Createfactory () method, Generates a specific Messageresourcefactory object (Note: Messageresourcesfactory is an abstract class). This allows you to invoke this specific messageresourcefactory Createresource () method to get the resource file defined in the configuration file (Web.xml).
The Application object type above is messageresources. You can specify a specific factory class when you configure Actionservlet in Web.xml. The Createresources () method cannot be messageresourcesfactory directly, because the method is abstract. The process of creating Factoryobject is as follows:
Messageresourcefactory factoryobject=