精华内容
下载资源
问答
  • 多线程的实现和使用场景

    万次阅读 2021-06-09 22:06:20
    多线程的实现和使用场景一、多线程实现方式1.1 Thread实现1.2 Runnable实现二、多线程使用场景1.多线程使用场景1.1 多线程应该最多的场景:1.2多线程的常见应用场景:2.多线程小案列2.1 多线程计算2.2 多线程实现...

    一、多线程实现方式

    1.1 Thread实现

    继承Thread类并重写它的run方法。之后创建这个子类的对象并调用start()方法。下面直接上代码:

    /**
    *描述
    * @author cy
    * @date 2021-06-09
    * @return
    **/
    public class TreadTest  extends  Thread{
        public static void main(String[] args) {
            //创建两个线程
            TreadTest thread1 = new TreadTest();
            TreadTest thread2 = new TreadTest();
            thread1.start();
            thread2.start();
        }
        @Override
        public void run() {
           for (int i = 0;i < 100;i++){
               //分别打印线程名称和i
               System.out.println("threadName:"
               +Thread.currentThread()+";i="+i);
           }
        }
    }
    

    输出结果可以看到两个线程交替打印。线程启动成功。
    在这里插入图片描述

    1.2 Runnable实现

    Runnable的实现方式是实现其接口,下面请看具体的实现代码

    
    /**
     * @author  cy
     * @date  2021-06-09
     *@deprecated  Runnable实现多线程
     */
    public class RunnableDemoTest {
    
        public static void main(String[] args) {
            //新建两个线程
            RunnableDemoTest1 r =  
            new RunnableDemoTest1();
            new Thread(r).start();
            new  Thread(r).start();
        }
    
        /**
         * 通过runnable 方式实现多线程
          */
    static class  RunnableDemoTest1  
                       implements  Runnable{
        @Override
        public void run() {
            for (int i = 0 ;i < 5 ;i++)
                System.out.println("threadName:"
                +Thread.currentThread()+";i="+i);
        }
    }
    }
    
    

    从输出结果中我们可以看到两个线程交替打印。线程启动成功。
    在这里插入图片描述

    二、多线程的使用场景

    1.多线程使用场景

    1.1 多线程应该最多的场景:

    web服务器本身; 各种专用服务器(如游戏服务器);

    1.2多线程的常见应用场景:

    1、后台任务,例如:定时向大量(100w以上)的用户发送邮件; 2、异步处理,例如:发微博、记录日志等; 3、分布式计算

    2.多线程小案列

    2.1 多线程计算

    计算一亿个数字之和,在没有学习多线程之前,也是可以实现的,我们可以通过循环一亿次进行累加,最后得出结果。
    代码如下:

    package trhead;
    
    import java.util.Random;
    
    /**
     * 计算一亿个数之和
     */
    public class SumThreadDemo {
    
        private static double [] nums = new double[1_0000_0000];
        private static Random r  =  new Random();
        private static  double  result = 0.0,result1 = 0.0,result2 = 0.0;
    
        static {
            for (int i =0;i < nums.length ; i++){
                nums[i] = r.nextDouble();
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            SumThreadDemo.m1();
            SumThreadDemo.m2();
        }
    
        /**
         * 使用单线程计算
         */
        private  static  void m1(){
            long startTime = System.currentTimeMillis();
            for (int i = 0;i < nums.length;i++){
                result += nums[i];
            }
            System.out.println(result);
            long endTime = System.currentTimeMillis();
            long countTime = endTime - startTime;
            System.out.println("m1耗时:"+countTime);
        }
    
        /**
         * 使用多线程计算
         */
        private  static  void m2() throws InterruptedException {
    
    
            Thread thread1 =   new Thread(()->{
                for (int i = 0;i < nums.length/2;i++){
                    result1 += nums[i];
                }
            });
    
            Thread thread2 =   new Thread(()->{
                for (int i = nums.length/2;i < nums.length;i++){
                    result2 += nums[i];
                }
            });
            long startTime = System.currentTimeMillis();
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(result1+ result2);
            long endTime = System.currentTimeMillis();
            long countTime = endTime - startTime;
            System.out.println("m2耗时:"+countTime);
        }
    
    
    
    }
    
    

    从输出结果中可以观察出,两个线程计算结果比单个线程快了将近两倍。如果实际应用中有这种场景,大家可以使用多线程实现。
    在这里插入图片描述

    2.2 多线程实现卖票小程序

    某电影院正在上映某大片,共5张票,而他又有3个售票窗口售票,请设计一个程序模拟该电影院售票。

    多线程实现方式1:

    package trhead;
    
    /**
    *描述
     *  某电影院正在上映某大片,共5张票,
     * 而他又有3个售票窗口售票,请设计一个程序模拟该电影院售票。
    * @author cy
    * @date 2021-06-09
    * @return
    **/
    public class TicketTreadTest extends  Thread{
        //设置票数
        private  int ticket = 5;
        public static void main(String[] args) {
            //创建两个线程
            TicketTreadTest thread1 
                  = new TicketTreadTest();
            TicketTreadTest thread2 
                  = new TicketTreadTest();
            TicketTreadTest thread3 
                  = new TicketTreadTest();
            thread1.start();
            thread2.start();
            thread3.start();
        }
        @Override
        public void run() {
            while(true){
               //分别打印线程名称 和 ticket 数
               System.out.println("threadName:"
               +Thread.currentThread()+";
               ticket="+ticket--);
               if(ticket < 0){
                   break;
                }
           }
        }
    }
    

    结果分析:从下图输出结果中可以分析,使用继承Thread类实现卖票,导致每个窗口都卖了五张票,而这个电影院总共才五张票,多线程出现了超卖现象。原因是继承Thread方式,是多线程多实例,无法实现资源的共享
    在这里插入图片描述

    2.3多线程卖票小程序优化

    在2.2的小程序案列中,我们发现了在多线程的环境下, 由于公共资源可能会被多个线程共享, 也就是多个线程可能会操作同一资源. 当多个线程操作同一块资源时, 很容易导致数据错乱或发生数据安全问题,
    即: 数据有可能丢失, 有可能增加, 有可能错乱.

    我们如何避免这种现象呢?具体看代码:

    package trhead;
    
    /**
     * @author  cy
     * @date  2021-06-09
     *@deprecated  Runnable实现多线程卖票
     */
    public class TicketRunnableDemoTest {
        //设置票数
        private  static int ticket = 5;
    
        public static void main(String[] args) {
            //新建两个线程
            RunnableDemoTest1 r 
                   =  new RunnableDemoTest1();
            new Thread(r).start();
            new  Thread(r).start();
        }
    
        /**
         * 通过runnable 方式实现多线程
          */
    static class  RunnableDemoTest1  
                        implements  Runnable{
        @Override
        public void run() {
            while (ticket > 0){
                saleTicket();
            }
        }
    
            /**
             * 实现卖票方法
             */
        public  void  saleTicket(){
            if(ticket>0){
                System.out.println("threadName:"
                +Thread.currentThread()
                + "正在出票,余票剩余:"+ticket-- +"张");
            }
        }
    }
    }
    
    

    结果分析:从下图输出结果中可以分析,实现Runnable接口进行卖票,电影院总共才五张票,多线程卖票正常。原因是实现Runnable方式,是多线程单实例,可实现资源的共享

    在这里插入图片描述

    2.4多线程卖票小程序优化升级

    细心的小伙伴可能会发现,怎么在2.3输出打印的票数不是从大到小排序的,这跟现实中的卖票场景不一样呐。如果想解决这样的问题,就必须使用同步,所谓的同步就是指多个操作在同一个时间段内只有一个线程进行,其他线程要等待此线程完成之后才可以继续执行
    下面我们通过对2.3代码进行继续优化,实现真实卖票场景。

     /**
    * 通过synchronized实现线程同步
      * 实现卖票方法
      */ public synchronized   void   saleTicket1(){
          if(ticket>0){
              System.out.println("threadName:"
              +Thread.currentThread()
                      + "正在出票,余票剩余:"
                      + +ticket-- +"张");
          }
      }
    

    结果分析:从下图输出结果中可以分析,通过同步代码的方法进行代码的加锁操作,实现了卖票场景。
    在这里插入图片描述


    总结

    这节主要给大家介绍了多线程的实现以及相应的一些使用场景,并且引入了同步的知识点,下一节主要介绍synchronized关键字的使用。
    另外,码字不容易,如果发现小编描述有误,麻烦指摘。

    展开全文
  • 深入浅出多线程编程实战(五)ThreadLocal详解(介绍、使用原理、应用场景) 文章目录一、ThreadLocal简介二、ThreadLocal与Synchronized区别三、ThreadLocal简单使用四、ThreadLocal原理五、ThreadLocal 应用场景 ...

    深入浅出多线程编程实战(五)ThreadLocal详解(介绍、使用、原理、应用场景)


    一、ThreadLocal简介

    ThreadLocal(是Thread Local Variable,线程局部变量)类是Java为线程安全提供的一个工具类,代表一个线程局部变量。把数据放在ThreadLocal中可以让每个线程创建一个该变量的副本,线程间可以独立地改变自己的副本,而不会和其他线程产生副本冲突,从而避免并发访问的线程安全问题,就像每个线程都完全拥有该变量一样。

    在这里插入图片描述


    二、ThreadLocal与Synchronized区别

    ThreadLocal其实是与线程绑定的一个变量。ThreadLocal和Synchonized都用于解决多线程并发访问。
    但是ThreadLocal与synchronized有本质的区别:
    1、Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
    2、Synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。
    而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。
    而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。

    在这里插入图片描述


    三、ThreadLocal简单使用

    方法:
    T get() 返回此线程局部变量的当前线程副本值
    void remove() 删除此线程局部变量的当前线程的副本值
    void set(T value) 设置此线程局部变量中当前线程副本值

    public class TheadLocalTest {
        private static ThreadLocal<Student> threadLocalStudent = new ThreadLocal<>();
        public static void main(String[] args) {
            // 简单写一个测试线程隔离的例子
            // 原料: 1个ThreadLocal类型的变量 2个线程
            // 期望结果:线程一set的变量 线程二get不到!
            new Thread(()->{
                Student student = new Student();
                System.out.println("线程一保存的对象:"+student.toString());
                threadLocalStudent.set(student);
            }).start();
            new Thread(()->{
                try {
                    // 细节!!! 先睡一会再get避免误差。
                    // 可见这是一个严谨性很高的测试Demo
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("期望结果:线程二获取的结果是null,说明线程二拿不到线程一存入的值");
                System.out.println("线程二获取结果:"+threadLocalStudent.get());
            }).start();
        }
    }
    

    运行结果:
    在这里插入图片描述

    四、ThreadLocal原理

    首先看一下ThreadLocal的类图,如下:
    在这里插入图片描述
    Thread、ThreadLocal、ThreadLocalMap的关系:
    1.Thread.threadLocals引用ThreadLocalMap,生命周期一致。
    2.ThreadLocal定义ThreadLocalMap
    3.ThreadLocalMap#Entry弱引用ThreadLocal。
    我们通常说一个对象不被引用就会被gc回收,其实说的是强引用。但弱引用对象是,不管有没有被引用都会被垃圾回收。

    ThreadLocal的数据结构:
    在这里插入图片描述
    Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,也就是说每个线程有一个自己的ThreadLocalMap。

    ThreadLocalMap有自己的独立实现,可以简单地将它的key视作ThreadLocal,value为代码中放入的值(实际上key并不是ThreadLocal本身,而是它的一个弱引用)。

    每个线程在往ThreadLocal里放值的时候,都会往自己的ThreadLocalMap里存,读也是以ThreadLocal作为引用,在自己的map里找对应的key,从而实现了线程隔离。

    ThreadLocalMap有点类似HashMap的结构,只是HashMap是由数组+链表实现的,而ThreadLocalMap中并没有链表结构。

    我们还要注意Entry, 它的key是ThreadLocal<?> k ,继承自WeakReference, 也就是我们常说的弱引用类型。

    五、ThreadLocal 应用场景

    场景1:
    ThreadLocal 用作保存每个线程独享的对象,为每个线程都创建一个副本,这样每个线程都可以修改自己所拥有的副本, 而不会影响其他线程的副本,确保了线程安全。
    场景2:
    ThreadLocal 用作每个线程内需要独立保存信息,以便供其他方法更方便地获取该信息的场景。每个线程获取到的信息可能都是不一样的,前面执行的方法保存了信息后,后续方法可以通过ThreadLocal 直接获取到,避免了传参,类似于全局变量的概念。

    展开全文
  • 认识多线程多线程使用场景

    千次阅读 2019-08-01 10:13:24
    1 一个对象里面如果有个synchronized方法,某一个时刻内,只要一个线程去调用 其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻 内,只能有唯一一个线程去访问这些synchronized方法 2 ...

    1  一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用
    其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻
    内,只能有唯一一个线程去访问这些synchronized方法
    2  锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的
    synchronized方法
    3  加个普通方法后发现和同步锁无关
    4  换成两个对象后,不是同一把锁了,情况立刻变化。
    5  都换成静态同步方法后,情况又变化
    所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实
    例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获
    取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实
    例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非
    静态同步方法释放锁就可以获取他们自己的锁。
    所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对
    象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个
    静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取
    锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同
    步方法之间,只要它们同一个类的实例对象!

    展开全文
  • 面试中的 ThreadLocal 原理和使用场景 前言 今天博主将为大家分享Java(面试必备):面试中的 ThreadLocal 原理和使用场景,不喜勿喷,如有异议欢迎讨论! 相信大家在面试中经常被问过 ThreadLocal 的原理和...

    面试中的 ThreadLocal 原理和使用场景


    前言

    今天博主将为大家分享Java(面试必备):面试中的 ThreadLocal 原理和使用场景,不喜勿喷,如有异议欢迎讨论!

    相信大家在面试中经常被问过 ThreadLocal 的原理和用法,虽然一直知道这个东西的存在但是一直没有好好的研究一下原理,没有自己的知识体系。今天安利一波有待提高


    ThreadLocal 是什么

    ThreadLocal 是 JDK java.lang 包中的一个用来实现相同线程数据共享不同的线程数据隔离的一个工具。 我们来看下 JDK 源码中是如何解释的:翻译后

    ThreadLocal
    这个类提供线程局部变量,这些变量与其他正常的变量的不同之处在于,每一个访问该变量的线程在其内部都有一个独立的初始化的变量副本;ThreadLocal
    实例变量通常采用private static在类中修饰。

    只要 ThreadLocal 的变量能被访问,并且线程存活,那每个线程都会持有 ThreadLocal
    变量的副本。当一个线程结束时,它所持有的所有 ThreadLocal 相对的实例副本都可被回收。

    一句话说就是 ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用(相同线程数据共享),也就是变量在线程间隔离(不同的线程数据隔离)而在方法或类间共享的场景。


    ThreadLocal 使用

     package com.test;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * 
     * @Description: 我的测试类
     * @ClassName: MyDemo.java
     * @author ChenYongJia
     * @Date 2019年4月17日 晚上23:25
     * @Email chen87647213@163.com
     */
    public class MyDemo {
    
    	private String string;
    
    	private String getString() {
    		return string;
    	}
    
    	private void setString(String string) {
    		this.string = string;
    	}
    
    	public static void main(String[] args) {
    		int threads = 9;
    		MyDemo demo = new MyDemo();
    		CountDownLatch countDownLatch = new CountDownLatch(threads);
    		for (int i = 0; i < threads; i++) {
    			Thread thread = new Thread(() -> {
    				demo.setString(Thread.currentThread().getName());
    				System.out.println("demo.getString()================>" + demo.getString());
    				countDownLatch.countDown();
    			}, "执行线程 - " + i);
    			thread.start();
    		}
    
    	}
    
    }
    

    控制台输出

    demo.getString()================>执行线程 - 0
    demo.getString()================>执行线程 - 1
    demo.getString()================>执行线程 - 2
    demo.getString()================>执行线程 - 3
    demo.getString()================>执行线程 - 4
    demo.getString()================>执行线程 - 6
    demo.getString()================>执行线程 - 7
    demo.getString()================>执行线程 - 5
    demo.getString()================>执行线程 - 8
    

    从结果可以看出多个线程在访问同一个变量的时候出现的异常,线程间的数据没有隔离。下面我们来看下采用 ThreadLocal 变量的方式来解决这个问题的例子。

    package com.test;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * 
     * @Description: 我的测试类
     * @ClassName: MyThreadLocalDemo.java
     * @author ChenYongJia
     * @Date 2019年4月17日 晚上23:28
     * @Email chen87647213@163.com
     */
    public class MyThreadLocalDemo {
    
    	private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    	private String getString() {
    		return threadLocal.get();
    	}
    
    	private void setString(String string) {
    		threadLocal.set(string);
    	}
    
    	public static void main(String[] args) {
    		int threads = 9;
    		MyThreadLocalDemo demo = new MyThreadLocalDemo();
    		CountDownLatch countDownLatch = new CountDownLatch(threads);
    		for (int i = 0; i < threads; i++) {
    			Thread thread = new Thread(() -> {
    				demo.setString(Thread.currentThread().getName());
    				System.out.println("demo.getString()================>" + demo.getString());
    				countDownLatch.countDown();
    			}, "执行线程 - " + i);
    			thread.start();
    		}
    	}
    
    }
    

    控制台输出

    demo.getString()================>执行线程 - 0
    demo.getString()================>执行线程 - 1
    demo.getString()================>执行线程 - 4
    demo.getString()================>执行线程 - 3
    demo.getString()================>执行线程 - 2
    demo.getString()================>执行线程 - 7
    demo.getString()================>执行线程 - 5
    demo.getString()================>执行线程 - 8
    demo.getString()================>执行线程 - 6
    

    从结果来看,这样很好的解决了多线程之间数据隔离的问题,十分方便。

    这里可能有的朋友会觉得在例子 1 中我们完全可以通过加锁来实现这个功能。是的没错,加锁确实可以解决这个问题,但是在这里我们强调的是线程数据隔离的问题,并不是多线程共享数据的问题。假如我们这里除了getString() 之外还有很多其他方法也要用到这个 String,这个时候各个方法之间就没有显式的数据传递过程了,都可以直接中 ThreadLocal 变量中获取,这才是 ThreadLocal 的核心,相同线程数据共享不同的线程数据隔离。

    由于ThreadLocal 是支持泛型的,这里采用的是存放一个 String 来演示,其实可以存放任何类型,效果都是一样的。


    ThreadLocal 源码分析

    在分析源码前我们明白一个事那就是对象实例与 ThreadLocal 变量的映射关系是由线程 Thread 来维护的,对象实例与 ThreadLocal 变量的映射关系是由线程 Thread 来维护的,对象实例与 ThreadLocal 变量的映射关系是由线程 Thread 来维护的。重要的事情说三遍。

    其实就是对象实例与 ThreadLocal 变量的映射关系是存放的一个 Map 里面(这个 Map 是个抽象的 Map 并不是 java.util 中的 Map ),而这个 Map 是 Thread 类的一个字段!而真正存放映射关系的 Map 就是 ThreadLocalMap。下面我们通过源码的中几个方法来看一下具体的实现。

    //set 方法
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    
    //获取线程中的ThreadLocalMap 字段!!
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
    
    //创建线程的变量
    void createMap(Thread t, T firstValue) {
         t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
    

    在 set 方法中首先获取当前线程,然后通过 getMap 获取到当前线程的 ThreadLocalMap 类型的变量 threadLocals,如果存在则直接赋值,如果不存在则给该线程创建 ThreadLocalMap 变量并赋值。赋值的时候这里的 this 就是调用变量的对象实例本身。

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }
    
    
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
    

    get 方法也比较简单,同样也是先获取当前线程的 ThreadLocalMap 变量,如果存在则返回值,不存在则创建并返回初始值。


    ThreadLocalMap 源码分析

    ThreadLocal 的底层实现都是通过 ThreadLocalMap 来实现的,我们先看下 ThreadLocalMap 的定义,然后再看下相应的 set 和 get 方法。

    static class ThreadLocalMap {
    
        /**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;
    
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
    
        /**
         * The table, resized as necessary.
         * table.length MUST always be a power of two.
         */
        private Entry[] table;
    }
    

    ThreadLocalMap 中使用 Entry[] 数组来存放对象实例与变量的关系,并且实例对象作为 key,变量作为 value 实现对应关系。并且这里的 key 采用的是对实例对象的弱引用,(因为我们这里的 key 是对象实例,每个对象实例有自己的生命周期,这里采用弱引用就可以在不影响对象实例生命周期的情况下对其引用)。

    private void set(ThreadLocal<?> key, Object value) {
    
        Entry[] tab = table;
        int len = tab.length;
        //获取 hash 值,用于数组中的下标
        int i = key.threadLocalHashCode & (len-1);
    
        //如果数组该位置有对象则进入
        for (Entry e = tab[i];
             e != null;
             e = tab[i = nextIndex(i, len)]) {
            ThreadLocal<?> k = e.get();
    
            //k 相等则覆盖旧值
            if (k == key) {
                e.value = value;
                return;
            }
    
            //此时说明此处 Entry 的 k 中的对象实例已经被回收了,需要替换掉这个位置的 key 和 value
            if (k == null) {
                replaceStaleEntry(key, value, i);
                return;
            }
        }
    
        //创建 Entry 对象
        tab[i] = new Entry(key, value);
        int sz = ++size;
        if (!cleanSomeSlots(i, sz) && sz >= threshold)
            rehash();
    }
    
    
    //获取 Entry
    private Entry getEntry(ThreadLocal<?> key) {
        int i = key.threadLocalHashCode & (table.length - 1);
        Entry e = table[i];
        if (e != null && e.get() == key)
            return e;
        else
            return getEntryAfterMiss(key, i, e);
    }
    

    看完了ThreadLocal相关的JDK源码 ,我自己也有了一定的了解,也希望能帮助到大家。


    到这里Java(面试必备):面试中的 ThreadLocal 原理和使用场景,分享完毕了,快去试试吧!


    最后

    • 在service层处理事务,可以用这个保存Connection对象。

    • 更多参考精彩博文请看这里:《陈永佳的博客》

    • 喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!


    展开全文
  • volatile的原理和使用场景

    千次阅读 2018-07-11 22:08:42
    上下文切换 CPU为每个线程分配时间片(几十ms),CPU不断切换线程执行,切换的时候会...为了降低开销我们应减少上下文切换,多线程竞争锁会引起上线文切换,CAS算法无需加锁,可以减少上线文切换,使用最少线程(...
  • Android 多线程: 完全解析线程池ThreadPool原理&使用

    万次阅读 多人点赞 2018-04-24 09:55:31
    对于多线程,大家应该很熟悉。但是,大家了解线程池吗? 今天,我将带大家全部学习关于线程池的所有知识。 目录 1. 简介 2. 工作原理 2.1 核心参数 线程池中有6个核心参数,具体如下 ...
  • 现在java线程编程应用广泛吗?哪些时候适合或必须要用多多线程编程呢?多线程的工作原理是怎样的呢?求大神们指导指导,谢了!
  • python可以实现多线程的方法有 thread(低版本使用的),threading Queue multiprocessing 其中threading客户以通过实例方法或者类方法来创建 多线程。 multiprocessing方法可以创建多线程池,用起来比较简洁、...
  • ZooKeeper原理使用场景

    万次阅读 2016-12-06 13:57:54
    ZooKeeper是Hadoop Ecosystem中非常...今天这篇文章分为三个部分来介绍ZooKeeper,第一部分介绍ZooKeeper的基本原理,第二部分介绍ZooKeeper提供的Client API的使用,第三部分介绍一些ZooKeeper典型的应用场景。 ...
  • 深入了解多线程原理

    万次阅读 2018-05-25 15:35:48
    使用多线程的目的 在多个CPU核心下,多线程的好处是显而易见的,不然多个CPU核心只跑一个线程其他的核心就都浪费了 即便不考虑多核心,在单核下,多线程也是有意义的,因为在一些操作,比如IO操作阻塞的时候,是不...
  • Nginx多线程原理

    千次阅读 2015-11-11 09:12:01
    一、问题 一般情况下,nginx 是一个事件处理器,一个从内核获取连接事件并告诉系统如何处理的控制器。实际上,在操作系统做读写数据调度的时候,nginx是协同...但是所有处理过程都是在一个简单的线程循环中完成的
  • 万字图解Java多线程

    万次阅读 多人点赞 2020-09-06 14:45:07
    我以前也是感觉学会了,但是真正有多线程的需求却不知道怎么下手,实际上还是对多线程这块知识了解不深刻,不知道多线程api的应用场景,不知道多线程的运行流程等等,本篇文章将使用实例+图解+源码的方式来解析java...
  • 并发编程(一)多线程基础和原理

    千次阅读 2020-07-19 01:44:02
    多线程基础 最近,准备回顾下多线程相关的知识体系,顺便在这里做个记录。 并发的发展历史 最早的计算机只能解决简单的数学运算问题,比如正弦、 余弦等。运行方式:程序员首先把程序写到纸上,然后穿 孔成卡片,...
  • Java多线程编程-(1)-线程安全锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁代码谈一下volatile关键字 Java多线程...
  • Java多线程的应用场景和应用举例

    千次阅读 2018-02-26 11:33:02
    多线程使用的主要目的在于:1、吞吐量:你做WEB,容器帮你做了多线程,但是他只能帮你做请求层面的。简单的说,可能就是一个请求一个线程。或多个请求一个线程。如果是单线程,那同时只能处理一个用户的请求。2、...
  • java并发包原理使用场景

    千次阅读 2018-10-20 14:20:17
    java并发包下有很内置的处理线程安全问题工具类,在集合中就有2种线程同步的类,比如:Vector较ArrayList线程安全,但是效率较低,同样的还有HashtableHashMap,在实际项目中常用ArrayList与HashMap,因为前者...
  • 多线程的应用在Android开发中是非常常见的,常用方法主要有: 继承Thread类 实现Runnable接口 Handler HandlerThread AsyncTask 今天,我将献上一份全面 & 详细的HandlerThread机制的学习指南,内容包括:...
  • 多线程锁的升级原理是什么?

    万次阅读 多人点赞 2019-05-20 11:04:06
    多线程锁的升级原理是什么? 锁的级别从低到高: 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁 锁分级别原因: 没有优化以前,sychronized是重量级锁(悲观锁),使用 wait notify、notifyAll 来切换...
  • Java 多线程:彻底搞懂线程池

    万次阅读 多人点赞 2019-07-09 19:27:00
    熟悉Java多线程编程的同学都知道,当我们线程创建过多时,容易引发内存溢出,因此我们就有必要使用线程池的技术了。 目录 1 线程池的优势 2 线程池的使用 3 线程池的工作原理 4 线程池的参数 4.1 任务队列...
  • 多线程对于共享变量访问带来的安全性问题 一个变量 i. 假如一个线程去访问这个变量进行修改,这个时候对于数据的修改访问没有任何问题。但是如果多个线程对于这同一个变量进行修改,就会存在一个数据安全性问题 ...
  • Java多线程编程-(8)-多图深入分析ThreadLocal原理

    万次阅读 多人点赞 2017-10-20 17:15:13
    前几篇:Java多线程编程-(1)-线程安全锁Synchronized概念Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性Java多线程编程-(3)-线程本地ThreadLocal的介绍与使用Java多线程编程-(4)-线程间通信...
  • 1 queue原理 1.1 queue简述 std::queue: 模板类queue定义在<queue>头文件中。队列(Queue)是一个容器适配器(Container adaptor)类型,被特别设计用来运行于FIFO(First-in first-out)场景,在该场景中,只能...
  • 转载请注明出处(万分感谢!): ...出自【zejian的博客】 关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) androi
  • 多线程、多进程的区别及适用场景

    千次阅读 2018-04-11 21:05:11
    对于多进程和多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,线程是CPU调度的最小单位”。多线程占相比于多进程占用内存少、CPU利用率高,创建销毁,切换都比较简单,速度很快。多进程相比于多线程...
  • 即JMeter如何实现多线程组并发测试,也就是Loadrunner中的混合场景测试时,该如何设置并发数?测试需求如下:对业务A、业务B、业务C、业务D、业务E,5个业务按并发比例要求进行100个用户并发的压力测试;JMeter是...
  • 多线程在随着cpu发展应用的是越来越多,游戏场景因为其在服务器所占的数据量与逻辑复杂度的原因必须依赖于它。为什么场景要采用多线程场景的线程是怎样的?场景的线程又是如何创建的?场景的线程又是怎样管理的?...
  • Java 原子变量原理使用场景

    千次阅读 2018-09-01 19:38:32
    他保证了多线程在同一时间操作一个原子变量而不会产生数据不一致的错误,并且他的性能优于使用同步机制保护的普通变量,譬如说在多线程环境 中统计次数就可以使用原子变量。 话不多说看源码: 通过比较...
  • 在某个Logstash的场景下,我产生了为什么不能用Flume代替Logstash的疑问,因此查阅了不少材料在这里总结,大部分都是前人的工作经验下,加了一些我自己的思考在里面,希望对大家有帮助。 大数据的数据采集工作是...
  • Java多线程

    万次阅读 多人点赞 2021-06-11 16:28:49
    Java多线程Java多线程线程的创建线程常见方法线程的状态线程的优先级守护线程线程组Java线程池线程池的创建线程池的参数线程池的使用线程不安全问题...InheritableThreadLocal的使用定时器Timer单例模式与多线程立即加载/饿汉模式延时加

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 188,391
精华内容 75,356
关键字:

多线程原理和使用场景