b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

Java多线程编程5(用于线程间通信的ThreadLocal)

电脑杂谈  发布时间:2020-07-14 06:23:44  来源:网络整理

linux线程编程_多线程编程_4核4线程 4核8线程

本文主要介绍如何解决非线程安全问题. 多亏了Java Multithreading Core Programming这本书,它为该系列文章提供了参考.

变量值的共享可以采用公共静态变量的形式. 所有线程都使用相同的公共静态变量. 如果您想认识到每个线程都有自己的共享变量,该怎么办? JDK中提供的ThreadLocal类是为解决此类问题而正式设计的.

ThreadLocal类的主要解决方案是将每个线程绑定到自己的线程. 可以将ThreadLocal类比作一个用于全局存储数据的框多线程编程,每个线程的私有数据都可以存储在框中.

例如:

多线程编程_linux线程编程_4核4线程 4核8线程

public class ThreadMain {
    public static ThreadLocal tl = new ThreadLocal();
    public static void main (String[] args){
        if (tl.get() == null) {
            System.out.println("从未放过值");
            tl.set("我的值");
        }
        System.out.println(tl.get());
        System.out.println(tl.get());
    }
}

运行结果为:

在这里插入图片描述

从结果来看,第一次调用tl对象的get()方法时返回的值为null,并且只有在调用set()方法之后才能检索该值.

多线程编程_4核4线程 4核8线程_linux线程编程

如下: 每个线程在设置和获取时都是自己的个人价值


    public class ThreadMain {
    public static void main(String[] args) {
        final ThreadLocal threadLocal = new ThreadLocal();
        Thread thread1 = new Thread(new Runnable() {
            @SuppressWarnings("all")
            public void run() {
                threadLocal.set("线程一得值");
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "----" + threadLocal.get());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        thread1.setName("线程一");
        thread1.start();
        Thread thread2 = new Thread(new Runnable() {
            @SuppressWarnings("all")
            public void run() {
                threadLocal.set("线程二得值");
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "----" + threadLocal.get());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        thread2.setName("线程二");
        thread2.start();
    }
}

我们可以继承ThreadLocal并重写其initialValue()方法,例如:

public class MyThreadLocal extends ThreadLocal {
    @Override
    protected Object initialValue() {
        return "我的初始值";
    }
}

4核4线程 4核8线程_多线程编程_linux线程编程

使用InheritableThreadLocal类让子线程从父线程获取值.

public class InheritableThreadLocalExt extends InheritableThreadLocal {
    @Override
    protected Object initialValue() {
        return "InheritableThreadLocalExt";
    }
}
public class ThreadMain {
    static InheritableThreadLocalExt inheritableThreadLocalExt = new InheritableThreadLocalExt();
    public static void main(String[] args) {
        try {
            for (int i = 0; i < 10; i++) {
                System.out.println("    在Main线程中取值="+inheritableThreadLocalExt.get());
                Thread.sleep(100);
            }
            Thread.sleep(2000);
            inheritableThreadLocalExt.set("first change");
            ThreadA threadA = new ThreadA();
            threadA.start();
            Thread.sleep(300);
            inheritableThreadLocalExt.set("second change");
            Thread.sleep(2000);
            System.out.println("last value = "+inheritableThreadLocalExt.get());
            new ThreadA().start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    static class ThreadA extends Thread {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("在ThreadA线程中取值=" + inheritableThreadLocalExt.get());
                    Thread.sleep(100);
                }
                inheritableThreadLocalExt.set("change");
                System.out.println("在ThreadA线程中取值=" + inheritableThreadLocalExt.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

结果:

在这里插入图片描述

4核4线程 4核8线程_linux线程编程_多线程编程

要知道的结果是: 当子线程调用get()方法时多线程编程,如线程中InheritableThreadLocal的初始值是继承的初始值,则它将始终是父线程中InheritableThreadLocal的当前值.

修改上面的InheritableThreadLocalExt代码,并将方法childValue重写为:

public class InheritableThreadLocalExt extends InheritableThreadLocal {
    @Override
    protected Object initialValue() {
        return "InheritableThreadLocalExt";
    }
    @Override
    protected Object childValue(Object parentValue) {
        return "child value";
    }
}

其他恒定运算结果为:

在这里插入图片描述

从结果中可以看出: 重写childValue方法后,无论父线程中InheritableThreadLocal的值如何,子线程中InheritableThreadLocal的初始值都是childValue中返回的值.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-279718-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 加藤奈奈绘
        加藤奈奈绘

        赔一件就行

      • 高乐乐
        高乐乐

        我就是我是颜色不一样的烟火

      • 何璐媛
        何璐媛

        但使得定远镇压也因此丧失了再战能力

      热点图片
      拼命载入中...