Development thread secure Spring web application
Author: Luo Shifei translated from: open-v.com
Foreword
If the developer is developing or maintaining a servlet-based web app, the Servlet specification suggestion is best to see. Because it contains content for web application developers to understand the working mechanism of the servlet container.
Among them, the specification gives how the servlet container handles the customer request. The servlet container will create a corresponding single case according to the respective servets defined in the web.xml configuration file. Therefore, multiple client requests may access these single examples simultaneously, that is, multiple threads simultaneously access them. It is important to ensure that thread security in web applications. Developers should remain vigilant about this issue, and must ensure that their respective code must be operated in a thread.
Warming thread safety
Ok, this article will introduce the basic knowledge of thread safety and how to implement thread safety. There are a lot of existing information, the author like Wikipedia [Translator Note: http://en.wikipedia.org/wiki/thread-safe]. Developers can basically think that if the code is reusable, or the code is implemented by some form of mutual exclusion, the code is a thread.
Most Java developers should have heard the synchronized keyword. Under the premise of any third party library, Java itself provides native support for threads, and synchronized keywords are often the most important factors in Java applications. Synchronization in Java provides mutual supporting support. Thread security is implemented by synchronizing a piece of code or the entire method can guarantee up to only a single thread. The introduction synchronization has side effects, that is, blocking. For example, Miss, the front desk of the big company or the lawyer, is also required to handle phone, email, interviewed customers, etc. This makes her work are busy, and some things cannot be dealt with in time.
Be alert to block in web applications. Synchronous code blocks make it handled while processing the throughput of the customer request, and many customers are obstructing, unless a customer processing is completed. Moreover, mutual exclusion will not only bring blocking, but also bring a deadlock. Usually, the deadlock is unrecoverable. The following conditions will trigger deadlocks: thread a locks the thread b waiting for resources, and thread b locks the thread a waiting for resources, that is, thread B has been waiting for thread a release lock, thread A. Therefore, for multi-threaded applications, the prevention and processing of deadlocks is usually very headache.
In addition, the SYNCHRONIZED keyword also enables a large number of synchronization objects to be used everywhere, thereby introducing the possibility of deadlocks. For example, the methods provided in java.util.hashtable and java.util.Vector are mutually exclusive, so they do not need to use them unless they need to use them. Developers only need to use java.util.hashmap and java.util.arraylist. Of course, synchronization methods in java.util.collections also use the synchronized keyword.
Although it is easier to manage, it introduces other issues. Reprinted code avoids sharing between thread data. Consider the following code (the way to think that Java is thread safe):
Public double pi () {
INT A = 22;
INT b = 7;
Return New Double (A / B);
}
Regardless of the thread that enters the method, it is always threaded. Each thread maintains a stack belonging to each thread and shares other threads. Where each thread is created in the current method (including the static method), it belongs to the current thread, i.e., stored in a stack in the current thread. Therefore, when threads A and B enter the above method, they will create a and b. Since the above method does not have data sharing, the above method is threaded. Please note: 22/7 values are close to PI, but they are not equal. Next, see how to optimize the above code.
PRIVATE DOUBLE PI = NULL;
Public double pi () {
IF (pi == null) {
PI = New Double (22/7);
}
Return Pi;
}
Although improved methods can improve performance, it is not reasonable. For example, if Pi is NULL, and threads A and B enter the fourth line. Therefore, threads A and B will test whether PI is empty, they will return true. Next, if the thread A continues (thread b is suspended due to some reason), then returns a reference to the memory address. Wherein, the memory address contains 22/7 results, that is, the PI value. Finally, thread a exits the method. When thread b enters the 5th line, the new memory address will overwrite the original memory address (line A is provided). This is too dangerous, and this problem is often difficult to debug.
If you use Threadlocal, you can not only ensure that the PI () method is thread security, but also provides performance improvement.
Private static threadlocal pi = new threereadlocal ();
Public double pi () {
IF (pi.get () == NULL) {
Pi.set (New Double (22/7));
}
Return (double) pi.get ();
}
The Threadlocal class is capable of wrapping any object and can bind objects to the current thread so that it only supplies the current thread. When the PI () method is executed primarily, since there is no object to be bound to the Threadlocal instance Pi, the get () method returns NULL. Bringing objects can be bound to the current thread by means of a set () method and is not available for other threads. Therefore, if different threads need to access the PI () method, by means of ThreadLocal, it is possible not only to ensure the thread security, but also improve performance.
Currently, there are many resources on how to use Threadlocal. Before Java 1.4, Threadlocal's performance is indeed very poor, but this problem has been solved. In addition, many developers are misused due to the wrong understanding of Threadlocal. Note that the above examples are absolutely no problem. After introducing Threadlocal, the behavior of the above method did not change, but the method is already a thread safe.
Developing thread security code requirements developers to use instance variables or static variables, especially for modifying those other threads need to use. Some occasions may be more appropriate. However, for identifying application performance bottlenecks caused by synchronization can only be completed by means of a professional performance evaluation tool or load test.
Thread security in web applications
Ok, after the knowledge of warming threads, how to think is how threads in web applications! Developers operate databases by creating a web page. For example, both the Web layer and the business logic layer can operate RDBMS. This article uses Hibernate to persist in business model into the database. In the web layer, developers can use Tapestry, Wicket, Struts, Webwork, JSF, Spring MVC, or other Web frameworks running in a web container. As for the specific implementation of the web layer is not the focus of this article. This article will pay attention to how to manage database connections, which is also the resource that handles thread security issues in web applications. Database connection objects, such as connectivity, result set, statement, hibernate session, is a status object. Of course, they are not threads, so they are not able to access multiple threads simultaneously. As mentioned earlier herein, developers should try to avoid synchronization. Whether it is synchronized keyword, or those synchronous classes (havehtable or vector), should avoid use as much as possible. Therefore, if you retrieve it, you do not have to process the blocking or deadlock.
Of course, through re-enter the implementation of thread security to access the database is not a simple job. For example, some developers may add a filter in the Servlet container configuration. Therefore, when the client requests, the filter will create a JDBC connection or hibernate session and bind them to the current thread with the ThreadLocal class, thereby uses to use it for business logic. If you use J2EE API directly, developers need to manage transactions, DB errors, etc. Please note that these maintenance work that is not related to business logic is often time.
Spring intrusion
Some Java developers may have heard of the DAO abstraction provided by Spring. Of course, some developers may also use it. Templates provided by Spring, developers can use DAO code reuse. With Spring AOP, developers can also use declarative transactions. Therefore, this article is to study how Spring is implemented in a thread security method to access RDBMS. For example, Spring allows databases to be accessed in JDBC, Hibernate, JDO, Ibatis, Toplink, etc. The examples given below are very common scenarios in corporate applications.
First, define the data source and used for Hibernate SessionFactory.
ID = "PropertyConfigurer" class = "org.springframework.beans.factory.config.propertyPlaceHolderConfigurer"> list> Property> bean> bean> Property> list> Property> prOPS> Property> bean> This is a typical configuration using Hibernate, which is connected to the database by defined data sources, and creates hibernate sessionFactory through local sessionFactory. Next, you need to define business objects (access to DB) and transaction manager (manage local transactions via Hibernate Session). Among them, the exposure of business objects can add new records in the database, and the transaction manager can wrap the method in the transaction. They are defined as follows. Public interface customerdao { Public Void CreateCustomer (Customer Customer); } Public class hibernatecustomerdao imports Customerdao { Private hibernateTemplate HibernateTemplate = NULL; Public void setsessionFactory (sessionFactory sessionFactory) { This.HibernateTemplate = New HibernateTemplate (sessionFactory, False); } Public Void CreateCustomer (Customer Customer) { This.HibernateTemplate.SAVE (Customer); } } Developers should have seen that the above class uses the HibernateTemplate provided by Spring. Note that the development of the template follows the best practice in the industry and will not be related to the business, but the J2EE API regulates those code to be processed. At the same time, it will be converted into an abnormality in an abnormality through DAO abstraction. Of course, Spring is not just providing templates using Hibernate, which also provides similar templates for JDBC, IBATIS, SQLMAP, JDO, Toplink. Since these templates and their real-alum variables achieve reinforcement, they are threaded, so the concurrent thread is allowed to use the template simultaneously. Using these templates not only enable the reuse of code, but also provides best practices. In addition to accessing DB in a thread security method, template also provides many other meaningful content. Ok, let's see how to define business objects and transaction managers! bean> bean> prOPS> Property> bean> If the developer is not familiar with the configuration of transaction management in Spring, this article is just satisfied with you. First, the Spring configuration segment defines the business object HibernateCustomerDao, which wraps Hibernate SessionFactory. Note that by default, JavaBean defined in Spring is single case, and HibernateCustomerDao is no exception. This means: Multiple threads may simultaneously perform the createCustomer () method. Second, the Hibernate transaction manager is configured, which has wrapped the same Hibernate SessionFactory instance. When the transaction manager is executed, it will complete the following things. First, check if the Hibernate session is bound to the current thread. If you have been bound, use it directly. If it is not binding, the Transaction Manager will inform Hibernate SessionFactory to create a new session and then bind the created session to the current thread. Second, if there is no event, the transaction manager will launch a new transaction and wrap the session. Otherwise, participate directly in the active transaction. The entire process is implemented by using the TransactionProxyFactoryBean provided by Spring. Of course, this is a transaction management process implemented in a statement. TransactionProxyFactoryBeans can create a proxy object for business objects to manage transactions through transaction managers. When you call the CreateCustomer () method each time, Transaction Manager will manage transactions based on transaction property. Currently, Spring provides the JDBC data source, JDO, Toplink, in addition to the HibernateTransactionManager transaction manager. Ok, let's take a look at the business object! When the CreateCustomer () method is called, HibernateTemplate will look up the Hibernate Session that is bound to the current thread. Since the above configuration file is incorporated into the second parameter of the HibernateTemplate builder is false, there is no abnormality that is not boundless if there is no binding Hibernate session. This is especially useful for fields and particularly useful (note, transaction manager). Once the transaction management is configured, the Hibernate Session will bind to the current thread, thus starting the transaction. Note that hibernateTemplate does not check if the transaction is activated, nor does it display or terminate transactions. Please also note that if there is an unexpected approximation in the declaration method (the transaction attribute), the current active transaction will roll back. As for the study of transaction attributes, this article is no longer given. in conclusion Finally, summarize Spring to implement data access in a thread security manner. By using transaction management and trade-offs Threadlocal, Spring binds database connections (JDBC connections, Hibernate session, JDO persistence managers) to the current thread, which is used for DAO templates. This article starts to study the database connection and do not share between threads. Spring not only provides a declarative transaction management, J2EE API abstraction, best practices, but also the template provided by threads. When using Spring access DB, thread security that is re-entered to implement the application is the most reliable, common practice.