2021-09-26

Java多线程详解

​ 2021-07-06 0点20分


02、线程,进程,程序
  • 程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。

  • 进程是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位。

  • 通常在一个进程中可以包含若干个线程,当然一个进程至少有一个线程,不然没有存在的意义。

    **很多多线程是模拟出来的,真正的多线程是指有多个CPU,即多核。

本章核心概念

1.线程是独立的执行路径;

2.在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;

3.main()称之为主线程,为系统的入口,用于执行整个程序;

4.在一个进程中,如果开辟了多个线程,线程的运行有调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预;

5.对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;

6.线程会带来额外的开销,如CPU调度时间,并发控制开销;

7.每个线程在自己的工作内存教会,内存控制不当会造成数据不一致。


02 线程创建

1.线程三种创建方式

  • 继承Thread类(重点)
    • 重写run()方法,编写线程执行体
    • 创建线程对象,调用start()方法启动线程
    • 不建议使用:避免OOP单继承局限性
  • 实现Runnable接口(重点)
    • 重写run()方法,
    • 启动线程:传入目标对象 + Thread对象.start() new Thread(对象名).start()
    • 推荐使用:避免单继承局限性,方便同一个对象被多个线程使用
  • 实现Callable接口(了解)
    • 实现Callable接口,需要返回值
    • 重写call()方法,需要抛出异常
    • 创建目标对象
    • 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(3);
    • 提交执行:Future<Boolean> result1 = ser.submit(t1);
    • 获取结果:boolean r1 = result1.get()
    • 关闭服务:ser.shutdownNow()

2.普通方法和调用多线程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HXK2jZc0-1632666167100)(Java多线程详解.assets\image-20210706092000318.png)]

3.commons.io

4.总结 线程开启不一定立即执行,由CPU调度


03 静态代理

1.总结

  • 真实 对象和代理对象都要实现同一个接口
  • 代理对象要代理真实角色(代理对象拥有真实对象的类实例)

04 Lambda表达式

1.理解函数式接口

  • ==定义:==任何接口,如果只包含唯一一个抽象方法,那么它就是一个 函数式接口;
  • 对于函数式接口,我们可以通过Lambda表达式来创建该接口的对象。

2.静态内部类,局部内部类、匿名内部类、

  • 局部内部类:在方法内部的类
  • 匿名内部类:没有类的接口,必须借助接口或者父类。(接口不能被实例化啊,这里又是怎么回事?)
ilike = new Ilike() {
    @Override
    public void lambda() {
        System.out.println("匿名内部类\t"+getClass().getName());
    }
};

注意,表达式结尾的“;”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SOm3lDsE-1632666167102)(Java多线程详解.assets/image-20210713143856890.png)]

3.Lambda表达式:

接口 = (参数) -> {方法体};

1.去掉返回值

  1. 去掉括号

  2. 去调花括号

  3. 总结

  • lambda表达式只能有一行的代码的情况下才能简化成为一行,如果有多行,那么就用代码块包裹。前提是接口为函数式接口;

  • 多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号。


05 线程状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oRcAfGEL-1632666167102)(Java多线程详解.assets/image-20210710154844132.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vu9uUGcj-1632666167103)(Java多线程详解.assets/image-20210710155059743.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pD3q8DA3-1632666167104)(Java多线程详解.assets/image-20210710155335670.png)]


06 线程停止

1.建议线程正常停止:利用次数,不建议死循环;

2.建议使用标志位:设置一个标志位;

3.不要使用stop或者destroy等过时或者JDK不建议使用的方法。


07 线程休眠
  • 每一个对象都有一个锁,sleep不会释放锁。
  • 模拟网络延时:放大问题的发生性
  • 模拟得倒计时

08 线程礼让
  • 让当前正在执行的线程暂停,但不阻塞
  • 将线程从运行转为就绪状态
  • 让CPU重新调度,==礼让不一定成功!==看CPU心情。

09 线程强制执行
  • Join合并线程,待此线程执行完毕后,再执行其他线程,其他线程阻塞(类似插队

  • 此方法阻塞,这是主动让别人插队?

1.死亡之后的线程是不能再次启动的-------线程不能启动两次。


10 线程的优先级

​ Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。

  • 线程优先级低只是意味着调度的概率低,而不是优先级低就不会被调用了,这都是看CPU的调度
  • 优先级的设定建议在start()调度前

11 守护线程

1.线程分为==用户线程守护线程;==

2.虚拟机必须确保用户线程执行完毕 ;

3.虚拟机不用等待守护线程执行完毕

4.如:后台记录操作日志、监控内存、垃圾回收

thread.setDaemon(true); 默认是false表示是用户线程,正常的线程都是用户线程……


12 线程同步机制
  • 并发:多个线程访问同一个对象,并且某些线程还想修改这个对象------>线程同步,线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用。

1.队列和锁

  • 线程同步形成条件:**队列 **+ ------>解决安全性

2.由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制synchronized,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放锁即可。

  • 一个线程持有锁会导致其他所有需要此锁的线程挂起
  • 在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时引起性能问题
  • 如果一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题。

3.每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。

4.super只能写在构造方法第一行。


13 同步方法和同步块
  • 静态方法的锁是所在类的Class对象,普通方法的锁是this对象。
13.1.同步方法

1.由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:

  • 同步方法:public synchronized void method(int args){}

    synchronized方法控制对 对象 的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行。

  • 缺点:容将一个大的方法申明为synchronized将会影响效率。

13.2 同步块

1.同步块:synchronized(Obj){}

2.Obj称之为同步监视器

  • Obj可以是任何对象,但是推荐使用共享资源作为同步监视器;
  • 同步方法中无需指定同步监视器,因为同步方法中的同步监视器就是this,就是这个对象本身,或者是class(反射)。

3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值