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中的值进行更改,那么子线程取到的值还是旧值。

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Python实现web聊天室「建议收藏」

    Python实现web聊天室「建议收藏」使用Python模块中的select模块实现web聊天室功能select模块Python中的select模块专注于I/O多路复用,提供了selectpollepoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqueue方法(freeBSD系统)参数:可接受四个参数(前三个必须)r…

  • phpstorm 2021.7.20 激活码【中文破解版】

    (phpstorm 2021.7.20 激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.htmlML…

  • javascript格式化输出的实现(MuJS)

    javascript格式化输出的实现(MuJS)MuJS是一款支持嵌入式开发的轻量级javascript解释器。javascript主要是针对web开发的脚本语言,所以主要借助浏览器来调试;但mujs针对的是嵌入式开发,调试时的交互主要靠输入输出终端,javascript本身是不支持的,所以需要调用c语言的打印函数来实现。下面给出两个例子,一个是普通输出,符合脚本语言的解释性语言的特点,不考虑变量的类型;另一个是简单的格式化输出。前一个…

    2022年10月31日
  • 安装cgal_cgi3.2

    安装cgal_cgi3.2在VisualStudio2008中安装CGAl(注意:整个安装过程需要网络连接,最后指示如何在windows中增加环境变量)1、下载需要的安装文件1)、首先下载CGAL(3.4)的安装程序,从http://gforge.inria.fr/frs/?group_id=52(在页面的最下面)2)、获得最新版本的CMake(目前是2.6.3),从http://www.cmake.or

  • 微商分销系统哪家好,要怎么做?

    微商分销系统哪家好,要怎么做?分销模式的本质是分享经济,wemall微商分销系统将传统商品高昂的推广费用让利给消费者,并抽取一定金额作为分销商的佣金。分销模式使消费者直接与商家沟通,增加用户粘性,促成品牌的口碑转化为流量,相比与零售,分销有着无可比拟的优势,这也使越来越多的微商分销系统涌现出来。微信封杀分…

  • 2017noip提高组初赛_noip2021初赛答案

    2017noip提高组初赛_noip2021初赛答案一:装饰器实现AOP///<summary>///装饰器模式实现静态代理///AOP在方法前后增加自定义的方法///</summary>publicclassDecoratorAOP{publicstaticvoidShow(){Useruser=newUser(){Name=”看看看看”,Password=”1231231231

发表回复

您的电子邮箱地址不会被公开。

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