2. [Mandatory] A meaningful thread name is helpful to trace the error information, so assign a name when creating threads or thread pools.
Positive example:
3. [Mandatory] Threads should be provided by thread pools. Explicitly creating threads is not allowed.
Note: Using thread pool can reduce the time of creating and destroying thread and save system resource. If we do not use thread pools, lots of similar threads will be created which lead to “running out of memory” or over-switching problems.
4. [Mandatory] A thread pool should be created by rather than Executors
. These would make the parameters of the thread pool understandable. It would also reduce the risk of running out of system resource.
Note: Below are the problems created by usage of
Executors
for thread pool creation:
1)FixedThreadPool
andSingleThreadPool
:
Maximum request queue sizeInteger.MAX_VALUE
. A large number of requests might cause OOM.
2)CachedThreadPool
andScheduledThreadPool
:
The number of threads which are allowed to be created isInteger.MAX_VALUE
. Creating too many threads might lead to OOM.
5. [Mandatory] SimpleDateFormat
is unsafe, do not define it as a static variable. If have to, lock or DateUtils
class must be used.
6. [Mandatory] remove()
method must be implemented by ThreadLocal
variables, especially when using thread pools in which threads are often reused. Otherwise, it may affect subsequent business logic and cause unexpected problems such as memory leak.
Positive example:
7. [Mandatory] In highly concurrent scenarios, performance of Lock
should be considered in synchronous calls. A block lock is better than a method lock. An object lock is better than a class lock.
8. [Mandatory] When adding locks to multiple resources, tables in the database and objects at the same time, locking sequence should be kept consistent to avoid deadlock.
Note: If thread 1 does update after adding lock to table A, B, C accordingly, the lock sequence of thread 2 should also be A, B, C, otherwise deadlock might happen.
9. [Mandatory] A lock needs to be used to avoid update failure when modifying one record concurrently. Add lock either in application layer, in cache, or add optimistic lock in the database by using version as update stamp.
Note: If access confliction probability is less than 20%, recommend to use optimistic lock, otherwise use pessimistic lock. Retry number of optimistic lock should be no less than 3.
10. [Mandatory] Run multiple TimeTask
by using ScheduledExecutorService
rather than Timer
because Timer
will kill all running threads in case of failing to catch exceptions.
11. [Recommended] When using CountDownLatch
to convert asynchronous operations to synchronous ones, each thread must call countdown
method before quitting. Make sure to catch any exception during thread running, to let countdown
method be executed. If main thread cannot reach method, program will return until timeout.
12. [Recommended] Avoid using Random
instance by multiple threads. Although it is safe to share this instance, competition on the same seed will damage performance.
Note:
Random
instance includes instances ofjava.util.Random
andMath.random()
.Positive example: After JDK7, API
ThreadLocalRandom
can be used directly. But before JDK7, instance needs to be created in each thread.
13. [Recommended] In concurrent scenarios, one easy solution to optimize the lazy initialization problem by using double-checked locking (referred to The Double-checked locking is broken Declaration), is to declare the object type as volatile
.
Counter example:
14. [For Reference] volatile
is used to solve the problem of invisible memory in multiple threads. Write-Once-Read-Many can solve variable synchronization problem. But Write-Many cannot settle thread safe problem. For count++
, use below example:
Note: In JDK8,
LongAdder
is recommended which reduces retry times of optimistic lock and has better performance thanAtomicLong
.
15. [For Reference] Resizing HashMap
when its capacity is not enough might cause dead link and high CPU usage because of high-concurrency. Avoid this risk in development.
16. [For Reference] ThreadLocal
cannot solve update problems of shared object. It is recommended to use a static ThreadLocal
object which is shared by all operations in the same thread.