Java geek

Related reading:

Java concurrent programming (A) knowledge map

Java concurrent programming atomicity Java concurrent programming visibility Java Concurrent programming Ordering Java Concurrent Programming Creating threads Overview Java Concurrent Programming Introduction (synchronized Java Concurrent Programming (8) Thread Life Cycle (9) Java Concurrent programming (9) Deadlock and deadlock bits Java concurrent programming (10) Java concurrent programming (10) Lock optimization Java Concurrent Programming introduction (11) Stream limiting scenarios and Spring Stream Limiting Scenarios (12) Producer and Consumer patterns – Java concurrent Programming Introduction (13) Read/write locks and cache templates Java Concurrent Programming Introduction (14) CountDownLatch application scenarios CyclicBarrier is an asynchronous task scheduling tool, with the CompleteFeature. You can use the CyclicBarrier to complete tasks. You can use the CyclicBarrier to complete tasks Common Locking scenarios and Locking tools # Volatile keyword


1. The scope of Java variables

1.1. Scope of variables in Java classes

From the perspective of a Java class, the scope of a Java variable is as follows:

import java.util.concurrent.TimeUnit; public class VariableScopeDemo { private static int classVariable; Private int instanceVariable; private int instanceVariable; Public static void increaseClassVariable() {log("classVariable++"); classVariable++; } public static int getClassVariable() { return classVariable; } public void increaseInstanceVariable() { instanceVariable++; } public int getInstanceVariable() { return instanceVariable; } public int increaseBlockVariable() { int blockVariable = 0; // block level variables that are visible only within the block blockVariable++; return blockVariable; } private static class Thread1 extends Thread { @Override public void run() { VariableScopeDemo.increaseClassVariable();  // Modify class level variables, }} private static class Thread2 extends Thread {@override public void run() {log("classVariable: " + VariableScopeDemo.getClassVariable()); } } private static void log(String msg) { System.out.println(msg); } private static void quietlySleep() { try { TimeUnit.SECONDS.sleep(1); } catch(InterruptedException e) { // nothing to do } } public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); quietlySleep(); // Ensure that thread1 first executes thread2.start(); VariableScopeDemo demo1 = new VariableScopeDemo(); VariableScopeDemo demo2 = new VariableScopeDemo(); demo1.increaseInstanceVariable(); / / won't change demo2 the value of the int instance1Variable. = not getInstanceVariable (); / / get the instance of the modified values int instance2Variable = demo2. GetInstanceVariable (); log("demo1 instanceVariable: " + instance1Variable); log("demo2 instanceVariable: " + instance2Variable); int instance1BlockVariable = demo1.increaseBlockVariable(); int instance2BlockVariable = demo2.increaseBlockVariable(); log("demo1 instance1BlockVariable: " + instance1BlockVariable); log("demo2 instance2BlockVariable: " + instance2BlockVariable); }}Copy the code

Log printing:

classVariable++
demo1 instanceVariable: 1
demo2 instanceVariable: 0
demo1 instance1BlockVariable: 1
demo2 instance2BlockVariable: 1
classVariable: 1
Copy the code

1.2. Scope of variables in the application

Applications here include Web applications and JAVA processes, where the scope of JAVA variables is:

2.Application variable – is shared throughout the Web Application, as long as the background Application exists. 3.Session variable – is shared in the Session, when the browser opens a website. If the browser closes the website, it will disappear. Different login users have different sessions 4. Thread variables – shared in threads, that is, ThreadLocal, as we’ll see today

2. ThreadLocal application scenarios

The ThreadLocal variable eliminates the need for arguments to be passed between different Java classes, which facilitates the printing of trace information. You can place business-irrelevant arguments such as TraceId, employee number, and so on in a ThreadLocal variable. It is retrieved from the ThreadLocal when the trace information is printed.

As the figure below shows, a ThreadLocal variable can be passed across multiple classes in a single business request thread:

2.1. Parameter passing example

public class ThreadLocalParamDemo { private static class Controller { public static void createUser(String traceId, String user) { log(String.format("[%s] Controller.createUser be called. user: [%s]", traceId, user)); Service.createUser(traceId, user); } } private static class Service { public static void createUser(String traceId, String user) { log(String.format("[%s] Service.createUser be called. user: [%s]", traceId, user)); Dao.createUser(traceId, user); } } private static class Dao { public static void createUser(String traceId, String user) { log(String.format("[%s] Dao.createUser be called. user: [%s]", traceId, user)); } } private static void log(String msg) { System.out.println(msg); } public static void main(String[] args) { String traceId = "10001"; String user = "Jack"; Controller.createUser(traceId, user); traceId = "10002"; user = "Leo"; Controller.createUser(traceId, user); }}Copy the code

Log printing:

[10001] Controller.createUser be called. user: [Jack]
[10001] Service.createUser be called. user: [Jack]
[10001] Dao.createUser be called. user: [Jack]
[10002] Controller.createUser be called. user: [Leo]
[10002] Service.createUser be called. user: [Leo]
[10002] Dao.createUser be called. user: [Leo]
Copy the code

2.2. ThreadLocal example

public class ThreadLocalDemo { private static long traceId = 10000; private static ThreadLocal<String> traceIdThreadLocal = new ThreadLocal<>(); private static class Controller { public static void createUser(String user) { log(String.format("[%s] Controller.createUser be called. user: [%s]", traceIdThreadLocal.get(), user)); Service.createUser(user); } } private static class Service { public static void createUser(String user) { log(String.format("[%s] Service.createUser be called. user: [%s]", traceIdThreadLocal.get(), user)); Dao.createUser(user); } } private static class Dao { public static void createUser(String user) { log(String.format("[%s] Dao.createUser be called. user: [%s]", traceIdThreadLocal.get(), user)); } } private static void log(String msg) { System.out.println(msg); } private static void nextTraceId() { traceId++; traceIdThreadLocal.set(String.valueOf(traceId)); } private static class CreateUserThread extends Thread { private String user; public CreateUserThread(String user) { this.user = user; } @Override public void run() { Controller.createUser(user); } } public static void main(String[] args) { CreateUserThread createUserThread1 = new CreateUserThread("Jack"); createUserThread1.start(); CreateUserThread createUserThread2 = new CreateUserThread("Leo"); createUserThread2.start(); }}Copy the code

2.3. Whether the parent thread shares the ThreadLocal variable

public class ThreadLocalChildDemo { private static ThreadLocal<String> traceIdThreadLocal = new ThreadLocal<>(); private static class ChildThread extends Thread { @Override public void run() { System.out.println(traceIdThreadLocal.get()); } } public static void main(String[] args) { traceIdThreadLocal.set("10001"); ChildThread childThread = new ChildThread(); childThread.start(); }}Copy the code

Log printing:

null
Copy the code

Note The ThreadLocal variable is shared only within the same thread.

2.4. Summarize the benefits of ThreadLocal

1. Thread safety. ThreadLocal is a thread-level variable that is not accessed across threads and is therefore thread safe.

2. Separate concerns and separate the parameters that the business does not need to pay attention to. The business code only needs to call the general trace method.

3. Using ThreadLocal to pass variables within the thread, the business method will not be modified due to changes in method parameters, keeping the method stable.


<– read left mark, left point like!