JAVA 多线程(7):join 与threadLocal

join:

说明:线程A等待线程B 的结果或者等待线程B执行结束

private static String test = "begin";
    public static void main(String[] args){

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
                test = "change";
            }
        },"线程A");
        System.out.println(test);
        t.start();
        try {
            t.join();
            System.out.println(test);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

输出:

由结果看出,主线程等待子线程结束后再继续执行。

join与synchronized 的不同在于:虽然都会阻塞,但是join内部使用的是wait 进行等待,而synchronized 使用的时候对象监视器。

 join(long)

说明:等待子线程指定时间后继续执行当前线程

对上面的代码进行更改:

输出:

由结果看出,主线程等待2秒,在子线程未执行完时不再等待。

join(long) 与 sleep(long)的区别在于:join是wait 在子线程执行完毕后会释放锁,但是sleep 不会。

注意的是由于join内部是wait实现,所以如果多个线程都在抢都一把锁,有可能会导致join后面的方法先执行。

线程拥有各自线程的共享变量:

ThreadLocal:每个线程绑定自己的值,存储各自线程的私有数据。

private static ThreadLocal<String> threadLocal = new ThreadLocal<String>();

    private static void setV(String v){
        threadLocal.set(v);
    }

    public static void main(String[] args){
        Thread t= new Thread(new Runnable() {
            @Override
            public void run() {
                setV("线程A的数据");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + threadLocal.get());
            }
        },"线程A");

        Thread t2= new Thread(new Runnable() {
            @Override
            public void run() {
                setV("线程B的数据");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + threadLocal.get());
            }
        },"线程B");
        t.start();
        t2.start();
        // 主线程set
        setV("主线程数据");

        System.out.println(Thread.currentThread().getName() + threadLocal.get());
    }

输出:

由结果看出 各自线程从threadLocal 取出的数据都是各自线程的数据,互不干涉。

设置threadLocal初始化值:重写threadlocal initialValue()方法,返回初始化值

public class ThreadLocalExt extends ThreadLocal{
    @Override
    protected Object initialValue() {
        return "我是初始化";
    }
}

把上面例子的start 和主线set注释

 输出:

成灰之前,抓紧时间做点事!!
原文地址:https://www.cnblogs.com/jony-it/p/10833328.html