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 and SingleThreadPool:
      Maximum request queue size Integer.MAX_VALUE. A large number of requests might cause OOM.
      2) CachedThreadPool and ScheduledThreadPool:
      The number of threads which are allowed to be created is Integer.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 of java.util.Random and Math.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 than AtomicLong.

    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.