What ThreadLocal that? And how to use ThreadLocal, how to use the service

What is ThreadLocal

As early version of the JDK 1.2 provides java.lang.ThreadLocal, ThreadLocal provide a new way to solve the problem of concurrent multi-threaded programs. Using this tool can be very simple class to write a beautiful multi-threaded programs.

When using ThreadLocal variable maintenance, ThreadLocal provided for each thread using the variable independent variable copy, each thread can independently change their copy without affecting other threads corresponding copy.

From the perspective of the thread of view, the target variable is like a thread local variable, which is meant to express the class name "Local".

Therefore, the code to write thread-local variables in Java to be relatively few clumsy, thus causing thread-local variables are not well in the popularity of Java developers in.

ThreadLocal interface methods

ThreadLocal class interface is very simple, only four methods, let's take a look:

  • void set (Object value) value of the current thread's thread local variables.

  • public Object get () method returns the current thread corresponding to the thread-local variables.

  • public void remove () the value of the local variables of the current thread deleted, the purpose is to reduce memory usage, which is a new method for JDK 5.0. It should be noted that, when the end of the thread, the thread local variable should automatically be garbage, so explicitly call this method to clear the thread local variable is not required to operate, but it can speed up the recovery of memory speed.

  • protected Object initialValue () returns to the initial value of the thread local variables, which is a method of a protected, apparently to allow subclasses designed cover. This method is a method to delay calling, call get () or set (Object) when the execution thread the first time, and only performed once. The default ThreadLocal in direct returns a null.

It is worth mentioning that in JDK5.0, ThreadLocal has support for generics, the class of the class name has become ThreadLocal. API methods been adjusted accordingly, the new version of the API methods are void set (T value), T get () and T initialValue ().

1, the definition of

ThreadLocal thread-local variables, a storage container is variable, this container is stored into variables can be taken at any position of the variable thread.

ThreadLocal variables in the use of separate threads, other threads can not be used to ensure the security of variables

2, Example

public class TestDemo {
	//用一个静态的变量来记录ThreadLocal对象,方法在任何地方法直接调用
	static ThreadLocal<String> local = new ThreadLocal<>();
	public static void main(String[] args) {
		new Thread(){
			public void run(){
				//在线程的任意地方设置变量
				local.set("你");
				method();
			}
		}.start();
		new Thread(){
			public void run(){
				local.set("好");
				method();
			}
		}.start();
	}
	public static void method(){
		//可以在当前线程的任意地方获取变量
		System.out.println(local.get());
	}
}

3. practical business needs

When a device two asynchronous callback interface, data is for the same record, to ensure data integrity, how would you do?

Known interfaces callback random order, can not know which callback to run

Table Structure:

id name num

Two callback parameter is the return of a field of table

such as:

Return a callback interface num field

Two return callback interface name field

They do not have a common identity, but yet there must be a record, how would you do?

My approach is a start:

To query data in the table in recent 10s, if not inserted, if there is to update operations
and vice versa another interface in the same way, first check whether the record exists, it is not inserted, if there is to update operations

But its disadvantages are also obvious, recording only records within ten seconds.

This time there with the ThreadLocal

Directly on the code

public class Test {
    //静态类 方便调用
    static ThreadLocal<Ta> local = new ThreadLocal<>();

    public static void main(String[] args) {
        //无论先调用哪个接口 都先将这个值插入到ThreadLocal中
        Ta ta = new Ta();
        ta.setId(1);
        local.set(ta);
        //因为我们不知道哪个回调先调用,所以先判断是否存在了
        if(local.get().getId()!=null){
            //存在的情况就在另一个回调中获取上一个回调中插入的值
            Ta ta1 = new Ta();
            ta1.setId(local.get().getId());
            ta1.setName("成功了");
            //记得再保存数据的时候先remove,再set进去
            local.remove();
            local.set(ta1);
            //这个时候我们就可以插入数据库了,保证了数据的完整性
        }
        method();

    }

    public static void method(){
        //可以在当前线程的任意地方获取变量
        //加上 .toString() 是因为我用的是实体类
        System.out.println(local.get().toString());
    }


    public static class  Ta{
		//实体类
        private  Integer id;
        private  String name;
        private  Integer num;

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getNum() {
            return num;
        }

        public void setNum(Integer num) {
            this.num = num;
        }

        @Override
        public String toString() {
            return "Ta{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", num=" + num +
                    '}';
        }
    }
}

This completes the above business needs, which is single-threaded.

4. The use of ThreadLocal in multiple threads

package com.test;  
  
public class TestNum {  
    // ①通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值  
    private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {  
        public Integer initialValue() {  
            return 0;  
        }  
    };  
  
    // ②获取下一个序列值  
    public int getNextNum() {  
        seqNum.set(seqNum.get() + 1);  
        return seqNum.get();  
    }  
  
    public static void main(String[] args) {  
        TestNum sn = new TestNum();  
        // ③ 3个线程共享sn,各自产生序列号  
        TestClient t1 = new TestClient(sn);  
        TestClient t2 = new TestClient(sn);  
        TestClient t3 = new TestClient(sn);  
        t1.start();  
        t2.start();  
        t3.start();  
    }  
  
    private static class TestClient extends Thread {  
        private TestNum sn;  
  
        public TestClient(TestNum sn) {  
            this.sn = sn;  
        }  
  
        public void run() {  
            for (int i = 0; i < 3; i++) {  
                // ④每个线程打出3个序列值  
                System.out.println("thread[" + Thread.currentThread().getName() + "] --> sn["  
                         + sn.getNextNum() + "]");  
            }  
        }  
    }  
}  

We define the subclass generally by way anonymous inner classes ThreadLocal provide an initial variable value, as in the example shown at ①. Generating a set of threads TestClient sequence number, the at ③, we generated three TestClient, they share the same TestNum instance. Running the above code, the following output results on the console:

thread[Thread-0] --> sn[1]
thread[Thread-1] --> sn[1]
thread[Thread-2] --> sn[1]
thread[Thread-1] --> sn[2]
thread[Thread-0] --> sn[2]
thread[Thread-1] --> sn[3]
thread[Thread-2] --> sn[2]
thread[Thread-0] --> sn[3]
thread[Thread-2] --> sn[3]

Inspection result information output, we found that although each thread ID generated share the same TestNum example, but they do not, interference may occur, but rather each independently generated sequence number, this is because we through each ThreadLocal a thread provides separate copies.

summary

ThreadLocal thread safety problem is the way to solve a very good, it solves the problem of variable concurrent access conflicts by providing a separate thread for each copy of the variable. In many cases, ThreadLocal than using synchronized thread synchronization mechanisms to address security issues simpler, more convenient, and the results of the program have higher concurrency.

Released two original articles · won praise 0 · Views 26

Guess you like

Origin blog.csdn.net/weixin_44248755/article/details/104816585