【读书笔记】多线程编程核心技术

5 篇文章 0 订阅
  • 多线程与单线程的区别?
    单线程下,任务是排队执行的,也就是同步,就像是在cmd下输入一条命令后, 必须等这条命令执行完才可以执行下一条命令;而多线程是异步的,线程被调用的时机是随机的,因此代码的运行结果与代码的执行顺序或是调用顺序(执行start()方法的顺序) 是无关的。

  • 实现多线程编程的方式:
    一共有两种: 1.继承Therad类 2.实现Runnable接口
    使用Thread类的方式创建新线程时,最大的局限性是不支持多继承,因为Java语言的特点是单根继承,所以为了多继承,可以用实现Runnable接口的方式。

  • 调用start()启动线程和run()启动线程的区别?
    调用start()方法会通知“线程规划器”,此线程已经准备就绪,等待调用线程对象的run()方法;而直接调用run()方法就不是异步执行而是同步执行,此时线程对象并不是交给“线程规划器”处理而是main主线程来调用run()方法,相当于是主线程下的一个顺序执行的任务,并不会在多线程下工作。

  • 多线程的执行是异步的,通过加锁实现同步,在任意时刻保证只有一个对象执行,避免线程不安全问题(多个线程对同一个对象中的实例变量进行操作时会出现值被更改、值不同步的情况,进而影响程序的执行流程,取到的数据可能是被修改过的数据,产生脏读),加锁的代码称为“互斥区”或“临界区”。

  • 停止线程的方式?
    Java中一个有三种方式终止正在运行的线程
    1.使用退出标志,使线程正常退出,也就是当run()方法完成后线程终止
    2.使用stop()方法强行终止线程
    3.使用interrupt()方法中断线程(interrupt()方法并不能中断一个线程,需要和isInterrupted()方法或interrupted()方法配合使用,利用return或是异常处理来终止线程)

public static boolean interrupted();会返回中断标志状态并改变中断标志
public boolean isInterrupted();仅仅返回中断标志的状态
如果在sleep状态下停止某一线程,会进入catch语句,并清除停止状态值,使之变成false

  • 暂停线程
    使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。这两个方法如果使用不当,极易造成公共同步对象的独占,使其他线程无法获得公共同步对象,而且容易导致因为线程暂停而导致数据不同步的情况。

  • 线程的优先级
    线程的优先级分为1–10这10个等级,线程的优先级具有继承性、随机性(优先级较高的线程不一定会先被执行)

  • 守护线程
    Java线程中有两种线程,一种是用户线程,一种是守护线程。守护线程是一种特殊的线程,他的特性具有陪伴的含义,当线程中不存在用户线程了,守护线程就会自动销毁。典型的守护线程是垃圾回收线程。

  • 非线程安全
    多个线程对同一个对象中的实例变量进行操作时会出现值被更改、值不同步的情况,进而影响程序的执行流程,取到的数据可能是被修改过的数据,产生脏读。
    非线程安全问题存在于实例变量中,如果是方法内部的私有变量,则不存在“非线程安全问题”

  • synchronized锁
    关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法当作锁,对于同一个对象被多个线程调用的情况下,哪个线程先执行,哪个线程就持有该方法所属对象的锁,其他线程只能处于等待状态。如果多个线程访问多个对象的对象锁,那么JVM就会创建多个锁。同一个对象的不同线程调用synchronized关键字声明的方法一定是排队运行的。
    synchronized关键字拥有锁重入的功能,当一个线程获得一个对象锁以后,再次请求此对象锁是可以再次得到该对象锁的,因此一个synchronized方法的内部调用本类其他synchronized方法时,是可以得到锁的。

  • 继承中的synchronized的注意点
    存在父子继承关系时,子类可以通过可重入锁调用父类的同步方法。
    同步不具有继承性,想要在子类中实现同步,还是需要在子类中添加synchronized关键字

对象锁
  • synchronized同步语句块
    synchronized代码块是对某一个对象加锁。不在synchronized代码块中就是异步执行,在synchronized代码块中就是同步执行。
    1.synchronized(this)是对当前对象加锁
    2.synchronized(Object obj)是对指定实例对象加锁
    如果每次上锁的实例对象不同,就会创建多个锁,线程的执行还是异步的;如果每次上锁的是同一个实例对象(同一个常量池String实例对象或是同一个Object对象(没有new新的对象)),并且由同一个对象的不同线程获取锁,那么这些线程拿到的就是同一把锁,即使用的“对象监视器”是同一个,就会使其他线程阻塞,排队执行同步代码块;;synchronized(非this)代码块锁住的不是this对象锁,因此不会阻塞其他线程执行同步方法或是synchronized(this)代码块

  • synchronized同步方法
    synchronized关键字声明在方法上,也是对this对象进行上锁;

全局锁
  • synchronized(类名.class){}是对整个类的所有实例对象上锁
  • synchronized关键字声明在staic方法上也是对整个类的所有实例进行上锁。
    Class锁会对类的所有实例对象起作用,即只要是指定类的实例对象的线程要来获取锁(不同的对象调用不同的线程获取锁),都会对这些线程进行同步,阻塞,排队执行。

  • 对于静态内部类的对象inner,如果使用synchronized(inner){}同步代码块实现同步,获取到inner对象 的锁后,会对所有(不论是不是相同对象)来请求获取静态内部类中静态同步方法(因为此时获取到的都是inner对象锁)锁的线程进行同步阻塞处理

  • 同步方法容易造成死循环,一直由一个线程获取锁不释放,导致其他线程不能访问同步资源,因此可以采用同步代码块的非this对象来解决这样的问题,因为不同的非this对象拿到的是不同的锁,就不会被阻塞。

  • 死锁
    由于多个线程之间共享同一片资源,一个资源在任意时刻只能被一个线程获取(互斥条件 ),线程对于已获得的资源没有使用完之前不能被其他线程强行剥夺(不可剥夺条件 ),只有自己使用完毕之后才会释放,只有被释放的资源才能被其他线程获取,否则就会阻塞等待。如果一个线程对已有 的资源不释放,而又去尝试获取其他被占用的资源(请求与保持 ),那么几个线程之间的等待关系形成了一个环(环路等待 ),就会造成死锁。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值