ThreadLocal

ThreadLocal 基础

多线程的原理概论

开启多线程的方式

  1. 继承Thread 重写run方法
  2. 实现接口 runnable 重写run 或者 使用thread的构造方法直接new runnable来重写run
package com.itheima.controller;

public class ThreadDemo {
    public static void main(String[] args) {
        System.out.println("这是主线程"); //main方法的主线程

        Thread thread = new Thread(new Thre()); //new Thread使用实现类开启

        Ot ot = new Ot();   //这是继承的方式开启线程

        new Thread(new Runnable() { //new Thread使用构造方法开启
            @Override
            public void run() {
                System.out.println("这也是一个线程任务");
            }
        }).start();
        
        thread.start();
        
        ot.start();
    }
}

小结:

开启线程的时候,只认run方法

当new Thread对象的时候 如果该对象的run方法没有被重写,那么就会自动去找runnable重写的run方法来开启线程

互斥与同步

互斥 : A 使用时 B必然等待 因为A在占用(锁)

同步 : A使用时, B等待,因为B要使用A完成之后的数据

等待唤醒机制 await() notify()

案例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A8RU8vah-1602380972641)(D:\Java总结文档\图解\多线程\唤醒机制1.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-obPZQcqO-1602380972642)(D:\Java总结文档\图解\多线程\唤醒机制2.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mlvdciu8-1602380972643)(D:\Java总结文档\图解\多线程\唤醒机制3.png)]

ThreadLocal的方法

方法申明作用
initialValue()返回当前线程局部变量的初始值
set()设置当前线程绑定的局部变量
get()获取当前线程绑定的局部变量
remove()移除当前线程绑定的局部变量

ThreadLocal作用

ThreadLocal的作用是 : 在开启多个线程的时候,每个线程要将共享数据作为自己独立的值进行使用,不会被相互访问到,此时需要用到ThreadLocal对每个线程的变量进行隔离。

ThreadLocal 和synchronized的区别

​ ThreadLocal 和synchronized都可以实现对数据的隔离,但是要分清使用的场景。

​ ThreadLocal 的主要作用是对共享变量进行隔离,每个线程都有一个自己的变量,此时可以为每个线程都隔离一份仅属于自己的变量,不会出现相互被访问的情况。(一变多)

​ synchronized的主要作用是为了对某一个共享资源进行封锁,此资源有且仅有一个,若每个线程隔离一个会失去其意义。为了使这个变量从开始到结束时的值都是正确的,不会出现线程安全问题,所以要“锁住“,只能排队访问。(买票等案例)(一不变)

​ 在如下的案例当中,虽然都可以使用并且实现隔离,但是此处使用threadLocal更合适,因为使用synchronized会严重影响系统在高并发时的效率,而此处我不需要对这三条输出语句进行封锁,也不满足有且仅有一个共享资源的前提,我只是需要对每一个线程的content变量进行隔离,所以采用ThreadLocal 更合适。

由两种打印的效果可以得出结论,第二种是在高速切换,第一种是在排队挨个执行

import java.util.*;

public class TTT {
        private  String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public static void main(String[] args) {
        TTT test = new TTT();
        for(int i = 0 ; i < 5 ; i++){
            Thread thread =new Thread(new Runnable() {
                @Override
                public void run() {
                    //使用synchronized
                    synchronized (TTT.class){
                    test.setContent(Thread.currentThread().getName()+"的数据");
                    System.out.println("-------------------------------------");
                    System.out.println(Thread.currentThread().getName()+"---->"+test.getContent());
                }
                }
            });
            thread.setName("线程"+i);  //为每个线程署名
            thread.start();   //开始线程任务
        }
    }
    }

打印效果

-------------------------------------
线程0---->线程0的数据
-------------------------------------
线程4---->线程4的数据
-------------------------------------
线程3---->线程3的数据
-------------------------------------
线程2---->线程2的数据
-------------------------------------
线程1---->线程1的数据

使用thread Local

import java.util.*;

public class TTT {
    
      ThreadLocal<String> threadLocal =  new ThreadLocal();
        private  String content;

    public String getContent() {
        return  threadLocal.get();
    }

    public void setContent(String content) {
        threadLocal.set(content);
    }

    public static void main(String[] args) {
        TTT test = new TTT();
        for(int i = 0 ; i < 5 ; i++){
            Thread thread =new Thread(new Runnable() {
                @Override
                public void run() {
                    test.setContent(Thread.currentThread().getName()+"的数据");
                    System.out.println("-------------------------------------");
                    System.out.println(Thread.currentThread().getName()+"---->"+test.getContent());
                }
            });
            thread.setName("线程"+i);
            thread.start();
        }
    }
    }

打印效果

-------------------------------------
线程1---->线程1的数据
-------------------------------------
-------------------------------------
线程2---->线程2的数据
-------------------------------------
-------------------------------------
线程4---->线程4的数据
线程3---->线程3的数据
线程0---->线程0的数据


线程2---->线程2的数据


线程4---->线程4的数据
线程3---->线程3的数据
线程0---->线程0的数据








评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值