ThreadLocal及CountDownLatch应用

ThreadLocal用于保存某个线程共享变量:
对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。
1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。
2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。
3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。
4、ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。

具体测试实例:


import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class ThreadLocalDemo {

    public static void main(String[] args) throws InterruptedException {

        int threads = 3;//三个线程
        /**
         * 线程内方法引用外部实例,必须要用final来修饰;
         * 如果不修饰,内部方法结束时,实例会被回收,这时其他线程仍需使用时会报错
         * CountDownLatch 线程计数器
         * 执行完某个线程后调用countDownLatch.countDown();减一
         * */
        final CountDownLatch countDownLatch = new CountDownLatch(threads);
        final InnerClass innerClass = new InnerClass();
        
        for (int i = 1; i <= threads; i++) {
            new Thread(new Runnable() {
                public void run() {
                    try {
                        TimeUnit.MILLISECONDS.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    for (int j = 0; j < 5; j++) {
                        innerClass.add(String.valueOf(j));
                        innerClass.print();
                    }
                    innerClass.set("hello world");
                    countDownLatch.countDown();//线程执行完后减一
                };
            }, "thread - " + i).start();
        }
        countDownLatch.await();//线程全部执行完(0)时,执行下面内容
        
        new Thread(new Runnable() {
            public void run() {
                System.out.println("111111111111111111111111111");
            };
        }).start();
    }
    
    private static class Counter {
        //每个线程都有自己的实例备份,线程之间数据互不影响
        private static ThreadLocal<StringBuilder> counter = new ThreadLocal<StringBuilder>() {
            @Override
            protected StringBuilder initialValue() {
                return new StringBuilder("--StringBuilder初始值--");//所以线程共享前的初始数据
            }
        };
        
    }

    private static class InnerClass {
        
        public void add(String newStr) {
            StringBuilder str = Counter.counter.get();
            Counter.counter.set(str.append(newStr));
        }

        public void print() {
            System.out.printf("Thread name:%s ,Value:%s\n",
                    Thread.currentThread().getName(), Counter.counter.get().toString());
        }

        public void set(String words) {
            Counter.counter.set(new StringBuilder(words));
            System.out.printf("Set, Thread name:%s ,Value:%s\n",
                    Thread.currentThread().getName(), Counter.counter.get().toString());
        }
        
    }

}

结果:

Thread name:thread - 3 ,Value:--StringBuilder初始值--0
Thread name:thread - 1 ,Value:--StringBuilder初始值--0
Thread name:thread - 2 ,Value:--StringBuilder初始值--0
Thread name:thread - 1 ,Value:--StringBuilder初始值--01
Thread name:thread - 3 ,Value:--StringBuilder初始值--01
Thread name:thread - 1 ,Value:--StringBuilder初始值--012
Thread name:thread - 2 ,Value:--StringBuilder初始值--01
Thread name:thread - 1 ,Value:--StringBuilder初始值--0123
Thread name:thread - 3 ,Value:--StringBuilder初始值--012
Thread name:thread - 1 ,Value:--StringBuilder初始值--01234
Thread name:thread - 2 ,Value:--StringBuilder初始值--012
Set, Thread name:thread - 1 ,Value:hello world
Thread name:thread - 3 ,Value:--StringBuilder初始值--0123
Thread name:thread - 2 ,Value:--StringBuilder初始值--0123
Thread name:thread - 2 ,Value:--StringBuilder初始值--01234
Thread name:thread - 3 ,Value:--StringBuilder初始值--01234
Set, Thread name:thread - 2 ,Value:hello world
Set, Thread name:thread - 3 ,Value:hello world
111111111111111111111111111
package com.ifly.simple.thread.threadLocal;

import java.util.concurrent.TimeUnit;

public class TestThreadLocal {

    public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){

        @Override
        protected Integer initialValue() {
            return 555;
        }
        
    };
    
    public static void main(String args[]) throws InterruptedException {
        threadLocal.set(123456);
        
        Thread threadOne = new ThreadOne(); // 线程1
        Thread threadTo = new ThreadTo(); // 线程2
        threadTo.start(); // 线程2开始执行
        TimeUnit.MILLISECONDS.sleep(100); // 睡眠, 以等待线程2执行完毕
        threadOne.start(); // 线程1开始执行
        TimeUnit.MILLISECONDS.sleep(100); // 睡眠, 以等待线程1执行完毕
        // 此时线程1和线程2都已经设置过值, 此处输出为空, 说明子线程与父线程之间也是互不影响的
        System.out.println("main: " + threadLocal.get());//main: 123456
        threadLocal.remove();
        System.out.println("main: " + threadLocal.get());//main: 555
    }
 
    /**
     * 线程1
     */
    private static class ThreadOne extends Thread {
        @Override
        public void run() {
            // 此时线程2已经调用过set(456), 此处输出为空, 说明线程之间是互不影响的
            System.out.println("ThreadOne: " + threadLocal.get());//ThreadOne: 555
            threadLocal.set(123);
            System.out.println("ThreadOne: " + threadLocal.get());//ThreadOne: 123
        }
    }
 
    /**
     * 线程2
     */
    private static class ThreadTo extends Thread {
        @Override
        public void run() {
            threadLocal.set(456); // 设置当前ThreadLocal的值为456
            System.out.println("ThreadTo: " + threadLocal.get());//ThreadTo: 456
        }
    }
    
}

你可能感兴趣的:(Java)