join方法的使用

join方法的使用一、join方法1.1jon方法的作用使所属的线程对象x正常执行run()方法中的任务,而使当前线程y无限期的阻塞,直到x线程销毁后再继续执行线程y后面的代码。join方法具有使线程排队运行的作用,有些类似同步的运行的效果。1.2join与synchronized的区别join在内部使用wait()方法进行等待,而synchronized关键字使用的是”对象监视器”原理作为同步。…

大家好,又见面了,我是你们的朋友全栈君。

一、join方法

1.1 jon方法的作用

使所属的线程对象x正常执行run()方法中的任务,而使当前线程y无限期的阻塞,直到x线程销毁后再继续执行线程y后面的代码。

join方法具有使线程排队运行的作用,有些类似同步的运行的效果。

1.2 join与synchronized的区别

join在内部使用wait()方法进行等待,而synchronized关键字使用的是”对象监视器”原理作为同步。

1.3 方法join与异常

在join过程中,如果当前线程对象被中断,则当前线程出现异常。比如join方法遇到interrupt(),可能会出现异常。

1.4 方法join(lang)的使用

lang是时间的参数
myThread类:

public class myThread extends Thread{
    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + "开始时间:" + System.currentTimeMillis());
            Thread.sleep(50000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

测试代码:

public class test {
    public static void main(String[] args) {
        try {
            myThread myThread = new myThread();
            myThread.start();
            myThread.join(2000);
            System.out.println(Thread.currentThread().getName() + "结束时间:" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果:

Thread-0开始时间:1557799194421
main结束时间:1557799196422

将join(2000)改成slepp(2000)效果一样,但是sleep()与join()对同步的处理上有区别:

1.5 join(long)与sleep(long)的区别

  • 方法long是在内部使用wait()方法来实现的,所以join(long)具有释放锁的特点
    join方法源码:
public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

当执行到wait()方法后,当前线程的锁被释放,其他线程就可以调用此线程中的同步方法了。
而Thread.sleep(long)却不释放锁。

1.6 join()方法的特点

join()方法大部分时间里先抢到锁,然后快速释放锁。

二、类TheadLoacl的使用

1.1 ThreadLoca类的背景

让每个线程都有自己私有的共享变量,而不是所有的线程都拥有一个共享变量。
该类解决的是变量在不同线程之间的隔离性的问题,也就是不同线程拥有自己的值,不同线程的值是可以放入Threadlocal类中进行保存的。

问题:
用同一个ThreadLocal对象,给不同两个线程设置私有共享变量:

public class test {
    public static void main(String[] args) {
       ThreadLocal local = new ThreadLocal();
        System.out.println(local.get());
        local.set("你好");
        System.out.println(local.get());
    }
}

1.2 验证线程变量的隔离性

子线程:

public class myThread extends Thread{
    ThreadLocal local;
    public myThread(ThreadLocal local){
        this.local = local;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            local.set("次线程" + i);
            System.out.println(local.get());
        }
    }
}

主线程:

public class test {
    public static void main(String[] args) {
        ThreadLocal local = new ThreadLocal();
        myThread my = new myThread(local);
        my.start();
        for (int i = 0; i < 100; i++) {
            local.set("主线程" + i);
            System.out.println(local.get());
        }
    }
}

结果:

"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.2.4\lib\idea_rt.jar=53954:C:\Program Files\JetBrains\IntelliJ IDEA 2018.2.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;D:\untitled2\out\production\untitled2" backup.test
主线程0
主线程1
主线程2
主线程3
次线程0
次线程1
次线程2
主线程4
主线程5

三、类InheritableThreadLocal

3.1 作用

在创建子线程时,子线程会接收所有可继承的线程局部变量的初始值,以获得父线程所具有的值。通常,子线程的值与父线程的值是一致的;但是,通过重写这个类中的 childValue 方法,子线程的值可以作为父线程值的一个任意函数。

3.2 子线程拿到父线程的值

类线程A继承主线程:

public class threadA extends Thread{
InheritableThreadLocal in = new InheritableThreadLocal();
public threadA(InheritableThreadLocal a){
    this.in = a;
}
    @Override
    public void run() {
        System.out.println(in.get());
    }
}

测试类:

public class test {
    public static void main(String[] args) {
        try {
            InheritableThreadLocal a = new InheritableThreadLocal();
            a.set("给主线程设置的值");
            Thread.sleep(1000);
            threadA threada = new threadA(a);
            threada.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果:

给主线程设置的值

子线程拿到了父线程设置的值。

3.3 常用方法

  • protected T childValue(T parentValue)
    parentvalue是从父线程继承下来的值,可以重写该函数,对继承下来的数据进行再一步的处理。
  • protected T initialValue()
    返回此线程局部变量的当前线程的“初始值”。线程第一次使用 get() 方法访问变量时将调用此方法,但如果线程之前调用了 set(T) 方法,则不会对该线程再调用 initialValue 方法。通常,此方法对每个线程最多调用一次,但如果在调用 get() 后又调用了 remove(),则可能再次调用此方法。
    该实现返回 null;如果程序员希望线程局部变量具有 null 以外的值,则必须为 ThreadLocal 创建子类,并重写此方法。通常将使用匿名内部类完成此操作。

3.4 子线程对拿到的父线程的值进行处理

test类:

public class test {
    public static void main(String[] args) {
        try {
            InheritableThreadLocal a = new InheritableThreadLocal(){
                @Override
                protected Object childValue(Object parentValue) {
                    return parentValue + "子线程将得到的父线程的值处理了一下";
                }
            };
            a.set("给主线程设置的值");
            Thread.sleep(1000);
            threadA threada = new threadA(a);
            threada.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果:
给主线程设置的值子线程将得到的父线程的值处理了一下

3.4 注意事项

如果子线程在获取值的同时,主线程将InteritableThreadLocal中的值进行更改,那么子线程取到的值还是旧值。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132261.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月11日 上午7:00
下一篇 2022年6月11日 上午7:00


相关推荐

  • c语言代码实现hash

    c语言代码实现hashinclude stdio h include stdlib h include string h defineBUCKET constchar key char value structhashEn next typedefstruc string h stdlib h stdio h

    2026年3月26日
    3
  • 模块结构图初涉

    模块结构图初涉模块结构图是用于描述系统模块结构的图形工具 不仅描述了系统的子系统结构与分层的模块结构 还清楚地表示了每个模块的功能模块 模块是可以组合 分解和更换的单元 是组成系统 易于处理的基本单位调用 在模块结构图中 用连接两个模块的箭头表示调用 箭头总是由调用模块指向被调用模块 但是应该理解成被调用模块执行后又返回到调用模块数据 当一个模块调用另一个模块时 调用模块可以把数据传送到被调用模块处

    2026年3月19日
    1
  • 深度学习之RNN循环神经网络(理论+图解+Python代码部分)[通俗易懂]

    深度学习之RNN循环神经网络(理论+图解+Python代码部分)[通俗易懂]目录前言一、普通神经网络二、循环神经网络1.前向传播2.反向传播算法BPTT3.自然语言处理之RNN 4.梯度问题4.1梯度爆炸4.2梯度消失:5.Keras建立RNN模型进行IMDb情感分析的Python代码前言前段时间实验室人手一本《DeepLearning》,本文章结合这本圣经和博客上各类知识以及我自己的理解和实践,针对RNN循环神经网络作出…

    2022年10月21日
    7
  • GoLangIDE激活码_在线激活

    (GoLangIDE激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~3Y…

    2022年3月30日
    276
  • web安全笔记_web攻防之业务安全实战指南

    web安全笔记_web攻防之业务安全实战指南writeinmydormitoryat‏‎9:47:05Friday,April7,2017bygiantbranch(一个当初想横跨web跟二进制的菜鸡)————致即将毕业的自己。这是我的安全之路系列第一篇,敬请期待第二篇:《我的安全之路——二进制与逆向篇》总览大一:基本都在学习学校的课程,C语言,C++,高数啊,不过分数还可以,在大一复习周还在php3小时光速入门呢大二

    2026年2月2日
    4
  • 样本方差与总体方差

    样本方差与总体方差样本方差与总体方差 一 方差 variance 衡量随机变量或一组数据时离散程度的度量 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 概率论中方差用来度量随机变量和其数学期望 即均值 之间的偏离程度 nbsp 统计中的方差 样本方差 是每个样本值与全体样本值的平均数之差的平方值的平均数 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp

    2026年3月17日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号