美文网首页
Java线程基础

Java线程基础

作者: simonenfp | 来源:发表于2020-06-12 13:22 被阅读0次

创建线程的三种方式:

  • ​ 继承Thread

  • ​ 实现Runnable接口,然后交给Thread执行

  • ​ 实现Callable接口,通过FutureTask,可以拿到回调值

    严格来说只有前两种(如Thread源码中注释所说)第三种其实是被包装成FutureTask交给Thread执行,而FutureTask实现RunnableFuture,RunnableFuture继承自Runnable)

线程相关的一些方法

  • sleep期间不会释放锁,结束后会进入就绪状态,调用sleep时如果interrupted为true,则会抛出InterruptedException异常,并清除interrupt状态为false,想要彻底打断,需要在捕获异常时再调用interrupt()

  • wait会释放锁,需要等待别人唤醒才能进入就绪状态

  • interrupt和谐的结束线程,设置标识

  • join可以实现顺序执行线程,直接获取当前线程的执行权执行自己,自己执行完后再执行当前线程

  • setDaemon(),为当前线程设置守护线程,当前线程结束,守护线程也会结束

线程的一些状态

image.png

注:**在显式锁调用lock()获取不到锁时会调用LockSupport.park()进入等待或者等待超时状态,不会进入阻塞态,只有使用synchronized关键字获取不到锁时才会进入阻塞态,等待状态是自己调用方法主动进入,而阻塞状态是被动进入

ThreadLocal理解

  • 每个Thread中都持有一个ThreadLocalMap对象,这个对象存储了一组以ThreadLocal对象为键,以本地线程变量为value的键值对,叫做Entry的数组。可以在不同的线程中通过同一个ThreadLocal的set方法设置不同的线程局部变量,键都是同一个ThreadLocal对象,但是值保存在不同的Thread的ThreadLocalMap里,这样再通过同一个ThreadLocal的get方法取的时候,同一个key,在不同的线程却从不同的ThreadLocalMap取,值也是各自线程之前保存的局部变量值,所以ThreadLocal能够实现线程间的“数据隔离”,获取当前线程的局部变量值,不受其他线程影响~
  • 每个Thread维护着一个ThreadLocalMap的引用
  • ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储
  • 调用ThreadLocal的set()方法时,实际上就是往自己线程Thread对象的ThreadLocalMap设置值,key是ThreadLocal对象,值是传递进来的对象
  • 调用ThreadLocal的get()方法时,实际上就是从各自的Thread对象的ThreadLocalMap获取值,key是ThreadLocal对象
  • ThreadLocal本身并不存储值,它只是作为一个key来让线程Thread对象从各自的ThreadLocalMap获取value。

线程池

  • 线程池的优势:

    • 降低资源消耗,通过重复利用自己创建的线程降低线程的创建和销毁造成的消耗
    • 提高响应速度,当任务到达时,任务可以不需要等到线程创建就可以立即执行
    • 提高线程的可管理性,线程是稀缺资源,无限的创建,不仅消耗资源,还会降低系统稳定性,线程池可以统一分配,调优和监控
  • 线程池参数

    • 核心线程数

    • 最大线程数

    • 线程空闲时存活

    • 存活时间单位

    • 阻塞队列

    • 创建线程工厂

    • 4种拒绝策略:1.默认策略直接抛出异常。2.抛弃这个任务。3.抛弃阻塞队列最靠前的。4.用调用者所在线程执行任务

  • 线程工作机制:

    • 如果当前运行的线程少于核心线程数,则创建新线程来执行任务(注意,执行这一步骤需要获取全局锁)。
    • 如果运行的线程等于或多于核心线程数,则将任务加入阻塞队列BlockingQueue。
    • 如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务。
    • 如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecution()方法。
  • 如何配置线程池

    • CPU密集型:CPU在不停的计算,从内存中取值纯计算。

      尽量使用较小的线程池,最大线程数一般为CPU核心数+1(由于内存比较紧张,会把一部分磁盘划分为虚拟内存,线程处理的数据同时存在虚拟内存,磁盘中时,操作系统需要把磁盘中的数据调度到虚拟内存中,磁盘中读取速度比虚拟内存中慢,此时就会把线程标记为页缺失状态,会等数据调度过来后再唤醒线程,这样会有空闲CPU),CPU核心数获取:Runtime.getRuntime().availableProcessors(), 因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,会造成CPU过度切换。

    • IO密集型:网络通讯、读写磁盘

      可以使用稍大的线程池,一般为2*CPU核心数。 IO密集型任务CPU使用率并不高,因此可以让CPU在等待IO的时候有其他线程去处理别的任务,充分利用CPU时间。

    • 混合型:以上两种都有,这种情况下,可以将任务分成IO密集型和CPU密集型任务,然后分别用不同的线程池去处理。 如果拆分之后两个任务执行时间有数据级的差距,那么拆分没有意义。
      因为先执行完的任务就要等后执行完的任务,最终的时间仍然取决于后执行完的任务,而且还要加上任务拆分与合并的开销,如果拆分之后两个任务执行时间差不多,那拆分效率更高

相关文章

  • 技术体系

    一,java核心 java基础,jvm,算法,多线程,设计模式 Java基础:java基础相关,全栈java基础 ...

  • Java多线程目录

    Java多线程目录 Java多线程1 线程基础Java多线程2 多个线程之间共享数据Java多线程3 原子性操作类...

  • android 多线程 — 线程的面试题和答案

    这里都是我从各个地方找来的资料,鸣谢: Java多线程干货系列—(一)Java多线程基础 JAVA多线程和并发基础...

  • Android中的多线程

    1. Java多线程基础 Java多线程,线程同步,线程通讯 2. Android常用线程 HandlerThre...

  • Java基础

    Java基础 集合基础 集合框架 多线程基础 多线程框架 反射 代理 集合基础 ArrayList LinkedL...

  • java多线程相关

    (一) 基础篇 01.Java多线程系列--“基础篇”01之 基本概念 02.Java多线程系列--“基础篇”02...

  • java线程入门基础(二)

    java线程入门基础(二) 一、认识Java里的线程 1.1 Java里的程序天生就是多线程的 一个Java程序从...

  • Java多线程高级特性(JDK8)

    [TOC] 一、Java多线程 1.Java多线程基础知识 Java 给多线程编程提供了内置的支持。一条线程指的是...

  • 高并发Java

    高并发Java(1):前言 高并发Java(2):多线程基础 高并发Java(3):Java内存模型和线程安全 高...

  • Java-并发编程知识点总结

    目录: 线程基础 线程池 各种各样的锁 并发容器 原子类 Java 内存模型 线程协作 AQS 框架 一、线程基础...

网友评论

      本文标题:Java线程基础

      本文链接:https://www.haomeiwen.com/subject/opsgtktx.html