|
|
Here are five hidden aspects of Java Threads that you may not have heard of. | | |
|
|
Sunday, January 18, 2015: Java is a steep learning language. You can never stop learning Java. There are many hidden aspects of this programming language that you keep revealing as the time pass by. Concurrent programing is challenging but at the same time it is highly scalable. Thread class in Java can be leveraged to perform multiple. Today we have listed five useful techniques and methods that threads support. | |
1. Thread Names:
Each thread in Java String has unique name. The default name values start from ‘Thread-0, Thread-1, Thread-2’ and so on. You can expose thread names in two ways. You can either use the thread constructors or you can use thread name setter. Thread names are mutable, you can change them during runtime. The thread name string is simple string object. Following the conventions to name your thread makes it simpler while debugging the code. Self assigned transaction ID can ease the user handling requests. You can cut down the time of error solving by using default thread names.
You can generate UUID of thread at entry point of your app. Thread UUID stays consistent as request of thread travels between nodes, processes and threads. In case one of the threads in thread pool hangs for long time, you can run jstack to take close look at the code. For example, after running jstack, you will see the following code:
“pool-1-thread-1″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800 nid=0x6d03 in Object.wait() [0x000000013ebcc000]
To simplify the confusion, you can set more suitable name by running,
Thread.currentThread().setName(Context + TID + Params + current Time, …);
If you run stack again, you will get more clear picture of the particular thread -
”Queue Processing Thread, MessageID: AB5CAD, type: AnalyzeGraph, queue: ACTIVE_PROD, Transaction_ID: 5678956, Start Time: 30/12/2014 17:37″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800 nid=0x6d03 in Object.wait() [0x000000013ebcc000]
By doing this, you will come to know the function of thread. If it gets stuck, you can use the transaction ID to start it all over again, retrace your steps and reproduce the error to isolate and solve it.
2. Thread Priorities:
You can set the priority value of thread between 1 (minimum) to 10 (maximum). The default value for priority of thread is always 5 (normal). Each new thread has same priority as it’s parent thread. We can access and manipulate the priority of thread by using getPriority () and setPriority() commands. You cannot set the priority of thread in constructors. Thread priorities are used to signal that to OS thread scheduler. However, not all threads have equal priority value as, each thread requires different level of attention from CPU.
Each Java thread automatically opens new native thread on OS level. The custom set Java priorities are translated to native priorities in different way in each platform. On Linux, you can include “-XX:+UseThreadPriorities” flag to set priorities. Thread priorities are just recommendations, they dont cover the whole spectrum of values. But, it is important to have your own logic for thread priorities to ensure your priorities are reflected in CPU time. You shouldn't rely solely on priorities though.
3. Thread Local Storage:
Thread Local is a concept derived from Thread class. It stores unique data for each thread. Thread class (java.lang.ThreadLocal) provides Thread Local Storage, you can create variables that are unique to each thread instances. You can also create custom fields as if threads are members of own Thread class. You can create ThreadLocal as either static variable or part of singleton.
ThreadLocal variable can have a transaction ID, it is recommended to have transaction ID as it comes handy if you have uncaught exception error in your code. You can manually implement UncaughExceptionHandler which also comes with Thread class. You can also create ThreadLocal by allocating designated chunk of memory to buffer by worker thread. ThreadLocal exists as long as the thread is alive. It doesn't not store any memory garbage unless you free it or the thread dies.
4. User Threads and Daemon Threads:
A user thread is foreground thread while the daemon thread is background. The main thread is user thread and each new thread gets it’s User or Daemon status according to the thread that created the new thread. If you manually set a thread as Daemon, all threads created by that thread will be marked as Daemon. When all the threads in your app are of daemon status, the process gets closed.
It is recommended that you should only change the thread status to Daemon when it is not critical. Changing thread status to daemon saves the hassle of closing thread properly, stopping everything at a time to end the process quickly. You must not change the status of critical threads to Daemon. Things that cannot be interrupted like, a database entry or completing an update.
5. Java Processor Affinity:
Processor Affinity is used to bundle the thread with specific CPU cores. Anything that specific thread executes is run exclusively on some specific core of CPU. OS thread scheduler takes care of this rile according to its own logic. The affinity eliminates the chance of thread switching cores automatically. The best way to determine the effect of processor affinity is by testing.
Java doesn't support processor affinity by default. On Linux you can use tastes command to set the processor affinity. For running Java processes, use the following command -
taskset -c 1 “java AboutToBePinned” taskset -c 1
Now you can use the open source Java-Thread-Affinity to insert new code. You can download the open source library written by Peter Lawrey from OpenHFT from Github. You can pin the thread by using following command -
AffinityLock al = AffinityLock.acquireLock();
The above five ways to look at threads can help you in dealing with your java project. These are the lesser known but useful techniques that threads support. Let us know if you know any other useful thread techniques. |
|
0 comments:
Post a Comment