Java线程局部变量是一种特殊的变量,它只能在当前线程中访问,而不能在其他线程中访问。它使用ThreadLocal类来实现,ThreadLocal为每个使用它的线程提供独立的变量副本,所以每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。
ThreadLocal是一个泛型,它有一个泛型参数T,表明该ThreadLocal存储的数据是T 类型。ThreadLocal通过get()方法来获取当前正在运行的Thread对应的T 类型数据;通过set()方法来设置当前正在运行的Thread对应的T 类型数据。
public class ThreadLocalTest { private static ThreadLocalthreadLocal = new ThreadLocal (){ @Override protected Integer initialValue(){ return 0; } }; public static void main(String[] args) { for (int i = 0; i < 5; i++) { new Thread(new MyRunnable(i)).start(); } } public static class MyRunnable implements Runnable{ private int index; public MyRunnable(int index){ this.index = index; } @Override public void run() { System.out.println("thread-" + index + " : " + threadLocal.get()); // 输出 thread-0 : 0 thread-1 : 0 thread-2 : 0 thread-3 : 0 thread-4 : 0 此时threadLocal中存储的都是初始化后的0 for (int i = 0; i < 10; i++) { // 每个thread加10 所以最后threadLocal中存储的应该是0,10,20,30,40 如果不使用ThreadLocal就会出错 因为多个thread共享一个变量 最后得到错误的值 而使用了ThreadLocal之后就不会出错了 因为每个thread都有自己单独的副本 所以不会相互干扰 保证了多thread并发时正常工作 Integer value = threadLocal.get(); // 获得当前thread对应的value 如上文所说 此时value=0,10,20,30,40 具体看index大小 value += 10; // value加10 此时value=10,20,30,40,50 具体看index大小 threadLocal.set(value); // 重新set回去 此时threadlocal中存储的也就是10,20,30,40,50 具体看index大小 } System.out.println("thread-" + index + " : " + threadLocal.get()); // 输出 thread-0 : 10 thread-1 : 20 thread-2 : 30 thread-3 : 40 thread-4 : 50 此时threadlocal中存储的也就是10,20,30,40,50 具体看index大小 } } }
线程局部变量分隔每个线程的变量的值。
java.lang包中的ThreadLocal类提供了一个线程局部变量的实现。
它有四个方法:get(),set(),remove()和initialValue()。
get()和set()方法分别用于获取和设置线程局部变量的值。
您可以使用remove()方法删除该值。
initialValue()方法设置变量的初始值,它具有受保护的访问。要使用它,子类ThreadLocal类并重写此方法。
以下代码显示如何使用ThreadLocal类。
public class Main { public static void main(String[] args) { new Thread(Main::run).start(); new Thread(Main::run).start(); } public static void run() { int counter = 3; System.out.println(Thread.currentThread().getName()+ " generated counter: " + counter); for (int i = 0; i < counter; i++) { CallTracker.call(); } } } class CallTracker { private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(); public static void call() { int counter = 0; Integer counterObject = threadLocal.get(); if (counterObject == null) { counter = 1; } else { counter = counterObject.intValue(); counter++; } threadLocal.set(counter); String threadName = Thread.currentThread().getName(); System.out.println("Call counter for " + threadName + " = " + counter); } }
上面的代码生成以下结果。
Java网络教程 -Java网络UDP套接字TCP套接字是面向连接的,基于流。基于UDP的套接字是无连接的,基于数据报。使用UDP发送的数据块...
Java网络教程 -Java网络TCP客户端套接字 Socket 类表示一个TCP客户端套接字。以下代码显示如何创建TCP客户端套接字:// Create S...
JavaFX教程 -JavaFX 选择框JavaFX框允许用户在几个选项之间快速选择。创建一个选择框我们可以使用ChoiceBox中的consturctors来创...
JavaFX教程 -JavaFX 进度显示器进度指示器以动态更改饼图的形式显示JavaFX中的操作进度。以下代码显示如何使用不确定值创建Progr...
Java日期时间 -Java时钟周期时钟 Clock 类表示真实世界的时钟。我们可以从Clock类中访问时区中的当前时间,日期和时间。我们可以...