目录

一、进程和线程的区别

1.1 进程

1.2 线程

二、并发和并行

2.1 并行

2.2  并发

2.3 监控线程的执行情况

三、创建方式

3.1 继承Thread类

思考:为什么不直接通过对象调用start()方法?

3.2 实现Runnable接口

3.3 使用Callable创建线程

3.4 Callable 和 Runnable的区别

继承Thread和实现Runnable接口两种方法的区别

3.5使用线程池例如Executor框架

3.5.1  概念

3.5.2  好处

3.5.3  线程池执行基本原理

3.5.4  线程池创建方式

3.5.5 线程池的分类

3.5.6 线程池的核心参数

四、常用方法

五、多线程实现方案

六、线程终止

七、常用方法

八、线程的生命周期

8.1 线程的状态

8.2 wait()、notify()、notifyAll()类比

九、 线程安全

9.1 安全问题原因​编辑

9.2  synchronized

9.3 Lock

9.4 线程锁

9.5 并发工具类  ConcurrentHashMap HashMap HashTable

9.6 线程死锁

9.7 释放锁

十、思考题

1.volatile关键字

2.count++ 是不是原子操作

3.怎么保证原子操作

4.原子类原理--CAS原理

5.ConcurrentHashMap HashMap 和HashTbale的区别



一、进程和线程的区别

1.1 进程

操作系统中正在运行的软件,比如我们使用的QQ,就启动了一个进程,操作系统就为该进程分配了新的内存空间,进程具有独立性,动态性和并发性

  1. 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
  2. 动态性:进程的实质是程序的一次执行过程,进程是动态产生的,动态是消亡的
  3. 并发性:任何进程都可以同其它进程一起并发执行

1.2 线程

线程是由进程创建的,是进程的一个实体,一个进程可以拥有多个线程。是进程中的单个顺序控制流,是一条执行路径。就是应用程序中做的事情。比如:360软件中的杀毒,扫描木马,清理垃圾
        单线程
            同一个时刻只允许执行一个线程
        多线程
            同一个时刻,可以执行多个线程
    线程
        用户线程
            也称为工作线程,当线程的任务执行完或以通知的方式结束
        守护线程
            一般是为工作线程服务的,当所有的用户线程结束后,守护线程自动结束,常见的守护线程有  垃圾回收机制
                应用:如果我们希望当main线程结束之后,子线程自动结束,只需要将子线程设置为守护线程即可。设置方法   实例.setDaemon(),位置在实例.start()之前
    注意:一个进程至少包括一个线程

二、并发和并行

2.1 并行

在同一时刻,有多个指令在多个CPU上同时执行
        造成一种 貌似同时 的错觉,简单的说,单核cpu实现的多任务就是并行

2.2  并发

在同一时刻,有多个指令在多个CPU上交替执行
        多核cpu可以执行并行
    Notes:并发、并行可以同时发生

2.3 监控线程的执行情况

在终端输入Jconsole可以监控线程的执行情况

三、创建方式

3.1 继承Thread类

在继承Thread类后,该类就可以当做线程使用。往往要重写run()(Thread实现了Runnable接口),在此方法内写入自己的业务逻辑,运行需要创建该类的实例,通过实例调用start方法。

思考:为什么不直接通过对象调用start()方法?

当我们运行一个程序时相当于启动了一个线程,当进程启动了以后,在进程开了一个主线程,当main线程执行 实例.start()主线程不会阻塞,会继续执行,如果直接去调用run(),此时的run()就是一个普通的方法,会发生阻塞,没有真正的开启一个线程,只有将run()执行完之后才会去执行其他的语句。真正实现多线程效果的是native 方法 start0()而不是run()。注start0()是由JVM调用,底层是c/c++来实现的(主线程执行完任务就会结束的,但是有子线程在运行时,进程也不会结束的,当所有的线程结束了,进程就结束了)

3.2 实现Runnable接口

Notes :java是单继承的,在某些情况下一个类可能已经继承了某个父类,这是再用继承Thread类方法来创建线程显然是已经不可能的了。因此Java设计者们提供了另一个方法创建线程,就是通过实现Runnable接口来实现方法
    运行需要新建一个线程,将实现Runnable接口的方法的类的实例放入线程的有参构造的方法,这里是使用设计模式的代理模式 。

3.3 使用Callable创建线程

和Runnable接口不一样,Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大。

3.4 Callable 和 Runnable的区别

  1. call()方法可以有返回值
  2. call()方法可以声明抛出异常 callable接口实现类中的run方法允许异常向上抛出,可以在内部处理,try catch,但是runnable接口实现类中run方法的异常必须在内部处理,不能抛出

callable和runnable都可以应用于executors。而thread类只支持runnable,

继承Thread和实现Runnable接口两种方法的区别

  1. 从java的设计来看,通过继承Thread或者实现Runnale接口来创建线程本质上没有区   别,Thread本质上也是实现了Runnable接口。
  2. 实现Runnbale接口的方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制

3.5使用线程池例如Executor框架

3.5.1  概念

盛放线程的容器,盛放线程的池子

3.5.2  好处

1. 减少频繁创建及销毁线程的操作,节省资源
       2. 线程池会将闲置的线程处理任务,达到线程复用

3.5.3  线程池执行基本原理

1.  创建一个池子,此时没有线程    pool.getPoolSize()
      2.   当第一次提交任务给线程池,线程池就会创建线程执行任务。当任务执行完毕。线程对象归还给池子线程并不会消亡
      3.当再次提交任务,此时线程池就会将闲置的线程去处置任务,如果没有闲置的线程,才会创建新的线程

3.5.4  线程池创建方式

创建线程池
             ExecutorService pool = Executors.newCachedThreadPool();
             线程池最多创建int最大值个线程
            ExecutorService pool = Executors.newFixedThreadPool(3);
             创建线程池对象,规定最大数
            创建一个线程池,根据需要创建新的线程,但在可用时将重用先前构建的线程
        方式一
           1. 创建一个任务对象
                MyTarget myTarget = new MyTarget();
           2. 提交任务给线程池
                pool.submit(myTarget);
                过去的方式   Thread t1 = new Thread(myTarget);
               缺点:自己创建线程,执行完任务,消亡浪费资源,系统资源开销大
           3. 如果不需要线程池,将其关闭
                pool.shutdown();
        方式二

匿名内部类

3.5.5 线程池的分类

3.5.6 线程池的核心参数

1. int corePoolSize

线程池核心线程大小,如果你的任务数量小于核心线程数,那么开启的线程数量还是三个

2.int maximumPoolSize

线程池最大线程数,基于KeepaliveTime会销毁

3.KeepaliveTime

空闲线程存活时间

4.TimeUnit 时间单位

时间单位,为 keepAliveTime 指定时间单位

5.workQueue  阻塞队列,用于保存任务的阻塞队列

1). ArrayBlockQueue 基于数组的有界队列,FIFO,防止资源耗尽问题

2). LinkedBlockQueue基于链表的无界阻塞队列,界值为Integer.MAX FIFO

Tips:maximumPoolSize参数是没有用的

3). SynchronousBlockQueue(不缓存任务队列)

Tips:maximumPoolSize参数是有用的,如果超过了会执行拒绝策略

4). ProprityBlockQueue() 几区Comparator实现,比较 无界阻塞队列

6.ThreadFactory

创建线程的工程类,例如守护线程daemon

7.RejectedExecutionHandler handler 拒绝策略

1). callerrunsPolicy(除非线程池shutdown,抛弃任务)

2). AbortPolicy(直接抛出异常)

3). DiscardPolicy(什么都不做,直接丢弃任务) //不建议用

4). DiscardOldestPolicy(什么都不做,直接丢弃队列里面最早的任务)

四、常用方法

用户线程:也叫工作线程,当线程的任务执行完或以通知方式结束

守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束

常见的守护线程:垃圾回收机制

五、多线程实现方案

六、线程终止

七、常用方法

八、线程的生命周期

8.1 线程的状态

8.2 wait()、notify()、notifyAll()类比

九、 线程安全

9.1 安全问题原因

解决方式

1.同步代码块

2.同步方法

3.Lock锁

9.2  synchronized

1、 Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。

2、每个对象都对应一个可称为互斥锁的标记,这个标记用来保证在任意时刻,只能有一个线程访问该对象。

3. 关键字sychronized来与对象的互斥锁联系,当某个对象用sychronized修饰时,表名该对象在任一时刻只能由一个线程访问。

4.同步的局限性:导致程序的执行效率要降低

5.同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)

6. 同步方法(静态的)的锁为当前类本身

Java中static作用及用法详解_CrazyCodeBoy的博客-CSDN博客_java static

被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。

被static关键字修饰的属性或方法不属于实例化的对象,而是属于类,而this属于当前操作的实例对象,所以同步static锁在了类上

public class demoSell{//静态方法public synchronized static void method1(){}//静态方法中的同步代码块public static void mehtod2(){synchronized(demoSell.class){}}
}

注意:

1.同步方法如果没有使用static修饰:默认所对象为this

2.如果方法使用static修饰,默认锁对象:当前类.class

3.实现的落地步骤

·需要先分析上锁的代码

·选择同步代码块或同步方法

·要求多个线程锁对象为同一个即可

1.同步代码块

synchronized(对象){//得到对象的锁,才能操作同步代码块
//需要被同步代码
}

2. sychronized还可以放在方法声明中,表示整个方法为同步方法

public synchronized void method(String name){
//需要被同步的代码
}

9.3 Lock

//创建可重复锁
Lock lock = new ReentrantLock();
//上锁
lock.lock();
//代码块
.............
//释放锁
lock.unlock();

9.4 线程锁

9.5 并发工具类  ConcurrentHashMap HashMap HashTable

9.6 线程死锁

概念:

多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程一定要避免死锁的发生

9.7 释放锁

1. 当前线程的同步方法,同步代码块执行结束后会自动释放锁

2. 当前线程在同步代码块,同步方法中遇到break、return

3. 当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束

4. 当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停并且释放锁

注意:下面的情况不会释放锁

1.线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行,不会释放锁。

2.线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁,应该避免使用suspend()和resume()来控制线程,方法不再推荐使用。

十、思考

1.volatile关键字

在多线程的情况下保证了数据的可见性,加了volatile的属性,一个线程修改后,另一个线程也能看到

原理:一个线程修改了数据,就会把数据刷新到主存中,其他线程读取到的副本就会失效,重新读取主存中的新数据

2.count++ 是不是原子操作

不是,三步操作,:

1.从主存中count的值存到A线成独有的空间

2.在线程独有工作空间中执行+1操作

3.将101重新刷新relaod到主存中

随时可能丢失CPU的执行权,比如在执行+1操作还未刷新到主存,就被其他线程B抢占

3.怎么保证原子操作

1.同步代码块

2.原子类AtomicInteger

4.原子类原理--CAS原理

在修改主存中的值,先拿旧值和主存中的值判断

如果相等,则直接修改

如果不等,说明已经有其他线程修改过了,需要重新获取主存中的新值

这里涉及到三个变量

1. 旧值: 第一次获取主存中值时,作为旧值存放在该变量中, 比如100

2. 新值 该线程操作后的值,比如执行++操作后的101

3.要修改的值 主存里面的值

如果旧值和要修改的值相等,说明没有被修改过,可以直接赋值

5.ConcurrentHashMap HashMap 和HashTbale的区别

HashMap效率最高 但是不安全

HashTable 效率最低 安全 每个方法都加锁

ConcurrenetHashp 效率第二高 安全

Java线程、Java多线程详细介绍相关推荐

  1. java中char占的二进制,java数据类型与二进制详细介绍

    java数据类型与二进制详细介绍 在java中 Int 类型的变量占 4个字节 Long 类型的变量占8个字节 一个程序就是一个世界,变量是这个程序的基本单位. Java基本数据类型 1. 整数类型 ...

  2. java线程池多线程优先级_Java线程优先级

    java线程池多线程优先级 Priority of a thread describes how early it gets execution and selected by the thread ...

  3. Java Scanner类的详细介绍(Java键盘输入)

    Java Scanner类的详细介绍(Java键盘输入) 一.Scanner类的简单使用 二.Scanner类的详细介绍 1.判断输入数据类型 2.next()与nextLine()的区别 3.求多个 ...

  4. Java自带的线程池ThreadPoolExecutor详细介绍说明和实例运用

    Java 5 开始,Java 提供了自己的线程池.线程池就是一个线程的容器,每次只执行额定数量的线程. java.util.concurrent.ThreadPoolExecutor 就是这样的线程池 ...

  5. java线程wait_java多线程学习(四) 之 wait和notify

    ynchronized让线程之间互斥,但是有时候因为业务逻辑,需要主动释放锁,让其它的线程执行,这就需要线程之间通信,我们知道JAVA里每个对象都有个隐式锁,JAVA为每个对象都提供了wait和not ...

  6. Java基础之多线程详细分析

    在了解多线程之前,先来了解一下进程与线程之间的关系. 进程和线程: 进程是指在系统中正在执行的一个程序,每个进程之间是独立的. 线程是进程的一个基本执行单元.一个进程要想执行任务,必须得有线程(每1个 ...

  7. Java中的多线程基本介绍

    在 Java 中,多线程是指同时执行两个或多个线程以最大限度地利用 CPU 的过程. Java 中的线程是一个轻量级进程,只需要较少的资源即可创建和共享进程资源. 多线程和多进程用于 Java 中的多 ...

  8. java.security Cipher 对象详细介绍

    cipher对象:此类为java.securtiy 为密码进行加密,解密的对象,根据java 1.6 doc javadoc 介绍: 此类为加密和解密提供密码功能.它构成了 Java Cryptogr ...

  9. Java线程之多线程与多进程(3)——Java中的多线程

    单线程 任何程序至少有一个线程,即使你没有主动地创建线程,程序从一开始执行就有一个默认的线程,被称为主线程,只有一个线程的程序称为单线程程序.如下面这一简单的代码,没有显示地创建一个线程,程序从mai ...

最新文章

  1. android多线程断点续传
  2. 在命令提示符输出c语言代码_您可以在Windows命令提示符中更改输出缓冲区的大小吗?...
  3. .某学校的学生公寓有14栋楼,用A~N这14个大写字母的其中一个代表楼号,每栋楼的层数为6层,用1~6六个数字表示。每层楼有40个房间,编号为01~40。具体表示一个宿舍房间时,用1个字母加3位数字表
  4. Could not find a version that satisfies the requirement Twisted=13.1.0 (from Scrapy)
  5. 仿58网,赶集网,百姓网swfupload图片上传效果(asp.net 2.0)
  6. git合并分支的时候将某个文件添加到忽略列表_常用的 Git 命令
  7. 虚拟机linux下git clone 报SSL connect error错误
  8. Atitit session机制的实现 目录 1. Web状态管理 Cookie 和 Session。 token 1 2. session 管理设计 1 2.1. session 的存储(可以
  9. ideaIU-2020.1.3的安装
  10. 在线版和离线版电路仿真以及开源电子硬件设计介绍
  11. 答疑解惑 | 关于PMBOK第七版,常见问题合集【附电子版】
  12. openresty 与 java RSA加解密
  13. opencv之重映射remap
  14. PySide2学习总结(三)QtWidgets和QML
  15. FER基于卷积神经网络: 处理少量数据和训练样本订单FER with CNN:Coping with few data and the training sample order
  16. Flash 游戏制作一些资源
  17. python--正则表达式匹配密码
  18. 1-4 Java方法和数组
  19. mysql 代码书写,【单选题】mysql 的代码书写规则是() A. 不区分大小写 B. 必须全部大写 C. 必须全部小写 D. 以上答案都不对...
  20. 领域驱动设计——柔性设计

热门文章

  1. CAD怎么打印黑白图纸?超简单的打印方法分享
  2. vagrant国内镜像源地址
  3. flash动画形变讨论二:低头
  4. 南京邮电大学微型计算机原理,南京邮电大学微型计算机原理与接口技术5-01章.ppt...
  5. 【汽车产业抢占AI赛道】北京汽车产业创新大集参赛项目盘点
  6. windows重命名文件脚本
  7. 独家对话小冰公司CEO李笛:小冰岛不是游戏,也不是元宇宙
  8. 涂鸦智能python 面试_利用Python配置Homeassistant,让涂鸦设备连接Homekit
  9. easyui与浏览器兼容模式的狗血
  10. 数组拼接html js,js数组合并的几种方法