- A thread-local variable effectively provides a separate copy of its value for each thread that uses it.
- ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread
- In case when multiple threads access a ThreadLocal instance, separate copy of Threadlocal variable is maintained for each thread.
- Common use is seen in DAO pattern where the DAO class can be singleton but the Database connection can be maintained separately for each thread. (Per Thread Singleton)
- public class Common {
- public synchronized void synchronizedMethod1() {
- System.out.println("synchronizedMethod1 called");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("synchronizedMethod1 done");
- }
- public void method1() {
- System.out.println("Method 1 called");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("Method 1 done");
- }
- }
- public class MyThread extends Thread {
- private int id = 0;
- private Common common;
- public MyThread(String name, int no, Common object) {
- super(name);
- common = object;
- id = no;
- }
- public void run() {
- System.out.println("Running Thread" + this.getName());
- try {
- if (id == 0) {
- common.synchronizedMethod1();
- } else {
- common.method1();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- Common c = new Common();
- MyThread t1 = new MyThread("MyThread-1", 0, c);
- MyThread t2 = new MyThread("MyThread-2", 1, c);
- t1.start();
- t2.start();
- }
- }
- Running ThreadMyThread-1
- synchronizedMethod1 called
- Running ThreadMyThread-2
- Method 1 called
- synchronizedMethod1 done
- Method 1 done
- public class Common {
- public synchronized void synchronizedMethod1() {
- System.out.println("synchronizedMethod1 called");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("synchronizedMethod1 done");
- }
- public synchronized void synchronizedMethod2() {
- System.out.println("synchronizedMethod2 called");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("synchronizedMethod2 done");
- }
- }
- public class MyThread extends Thread {
- private int id = 0;
- private Common common;
- public MyThread(String name, int no, Common object) {
- super(name);
- common = object;
- id = no;
- }
- public void run() {
- System.out.println("Running Thread" + this.getName());
- try {
- if (id == 0) {
- common.synchronizedMethod1();
- } else {
- common.synchronizedMethod2();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- Common c = new Common();
- MyThread t1 = new MyThread("MyThread-1", 0, c);
- MyThread t2 = new MyThread("MyThread-2", 1, c);
- t1.start();
- t2.start();
- }
- }
- When two threads call Thread.join() on each other.
- When two threads use nested synchronized blocks to lock two objects and the blocks lock the same objects in different order.
LiveLock
Livelock occurs when all threads are blocked, or are otherwise unable to proceed due to unavailability of required resources, and the non-existence of any unblocked thread to make those resources available. In terms of Java API, thread livelock can occur in following conditions:- When all the threads in a program execute Object.wait(0) on an object with zero parameter. The program is live-locked and cannot proceed until one or more threads call Object.notify() or Object.notifyAll() on the relevant objects. Because all the threads are blocked, neither call can be made.
- When all the threads in a program are stuck in infinite loops.
Starvation
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked. Starvation occurs when one thread cannot access the CPU because one or more other threads are monopolizing the CPU. In Java, thread starvation can be caused by setting thread priorities inappropriately. A lower-priority thread can be starved by higher-priority threads if the higher-priority threads do not yield control of the CPU from time to time.- findMonitorDeadlockedThreads() - This method can be used to detect cycles of threads that are in deadlock waiting to acquire object monitors. It returns an array of thread IDs that are deadlocked waiting on monitor.
- findDeadlockedThreads() - It returns an array of thread IDs that are deadlocked waiting on monitor or ownable synchronizers.
- Simple to construct, test, and use.
- Automatically thread-safe and have no synchronization issues.
- Step 1
On UNIX, Linux and Mac OSX Environment run below command:
ps -el | grep java
On Windows:
Press Ctrl+Shift+Esc to open the task manager and find the PID of the java process
- Step 2:
Use jstack command to print the Java stack traces for a given Java process PID
jstack [PID]
More details of jstack command can be found here : JSTACK Command Manual
- Give unique and descriptive names to the threads created in application. - Add log entry in all thread at various entry and exit points in threads.
- Change debugging config levels (debug, info, error etc) and analyze log messages.
- When you find the class that is leaking out threads check how new threads are instantiated and how they're closed.
- Make sure the thread is Guaranteed to close properly by doing following - Handling all Exceptions properly.
- Make sure the thread is Guaranteed to close properly by doing following
- Handling all Exceptions properly.
- releasing all resources (e.g. connections, files etc) before it closes.
- Using thread pools minimizes the JVM overhead due to thread creation. Thread objects use a significant amount of memory, and in a large-scale application, allocating and de-allocating many thread objects creates a significant memory management overhead.
- You have control over the maximum number of tasks that are being processed in parallel (= number of threads in the pool).
Java Interview Preparation Tips-Part 4: Threading Interview Questions
最新推荐文章于 2024-11-12 21:14:07 发布
本文深入探讨了Java中多线程同步的概念、不同线程的使用方式、线程启动与运行的区别、ThreadLocal变量的应用、InvalidMonitorStateException的抛出原因、线程睡眠与暂停的区别、静态方法同步的影响、非同步实例方法调用的可能、线程死锁与饥饿现象、Java线程泄露检测方法、线程池的使用理由及限制、构造方法同步的实现、Java线程资源管理与生命周期控制等关键知识点。
摘要由CSDN通过智能技术生成