多线程,同步

多线程

1. 多线程的优缺点
优点
  1. 提升资源利用率
  2. 提高用户体验
缺点
  1. 降低了其他线程的执行概率
  2. 用户会感受到软件的卡顿问题
  3. 增加了系统资源的压力
  4. 多线程情况下的资源共享问题,线程冲突,线程安全问题
2. 创建自定义线程类的两种方式

class Thread类
Java中的一个线程类
Thread类是Runnable接口的实现类,同时提供了很多线程的操作使用的方法

interface Runnable接口
这里规定了what will be run?
里面只有一个方法 run方法

方式一:

自定义线程类,继承Thread类,重写run方法

创建自定义线程类对象,直接调用start方法,开启线程

方式二:

自定义线程类,遵从Runnable接口

使用自定义遵从接口Runnable实现类对象,作为Thread构造方法参数

借助Thread类对象和start方法,开启线程

【推荐】

以上两种方式,推荐使用方式二,遵从Runnable接口来 完成自定义线程,不影响正常的继承逻辑,并且可以使用匿名 内部类来完成线程代码块的书写

3. 自定义线程执行流程简述

在这里插入图片描述

4. Thread类需要了解的方法
  1. 构造方法 Constructor
    Thread();
    分配一个新的线程对象,无目标,无指定名字

    Thread(Runnable target);
    创建一个新的线程对象,并且在创建线程对象的过程中,使用Runnable接口的实现类 对象作为执行的线程代码块目标

    Thread(String name);
    创建一个新的线程,无指定目标,但是指定当前线程的名字是什么

    Thread(Runnable target, String name);
    创建一个线程的线程对象,使用Runnable接口实现 类对象,作为执行目标,并且指定 name作为线程名

  2. 成员方法:

    void setName(String name);
    String getName();
    以上两个是name属性setter和getter方法

    void setPriority(int Priority);
    设置线程的优先级,非一定执行要求,只是增加执行的概率
    优先级数值范围 [1 - 10] 10最高 1最低 5默认

    int getPriority();
    获取线程优先级 void start(); 启动线程对象

    public static void sleep(int ms);
    当前方法是静态方法,通过Thread类调用,要求是当前所在线程代码块对应的线程, 进行休眠操作,休眠指定的毫秒数

    public static Thread currentThread();
    当前方法是静态方法,通过Thread类调用,获取当 前所处代码块对应的线程对象。

线程安全问题和解决方案

1. 线程安全问题—贡献资源能使用问题

在这里插入图片描述

2. 同步代码块

synchronized (/* 锁对象 */) {

}

特征:
  1. synchronized 小括号里面的对象是锁对象,并且要 求如果是多线程的情况下,锁对象必须是同一个对象。
  2. synchronized 大括号中的代码块就是需要进行同步的代码,或者说是加锁的代码,大括号里面的内容,有且只允 许一个线程进入。
  3. 同步代码块越短越好,在保证安全的情况下,提高性能问题:
    a. 目前锁对象感觉很随意,存在一定的隐患
    b. 代码层级关系很复杂,看着有点麻烦
3. 同步方法

synchronized 作为关键字来修饰方法,修饰的方法就是对应的同步方法。有且只有一个线程进入,到底是谁来完成加锁操作?

  1. 静态成员方法
    锁对象,是当前类对应的字节码文件 .class 类名.class
  2. 非静态成员方法
    锁对象就是当前类对象 this

选择同步方法是否使用static修饰问题

  1. 如果非static修饰,要保证执行的线程对象有且只有一个,因为锁对象当前线程对

  2. 如果是static修饰,锁对象具有唯一性,多个线程使用的锁是同一个锁

4. Lock锁
  1. 对象化操作。
    Lock lock = new ReentrantLock();
  2. 方法化操作
    开锁:
    unlock();
    加锁:
    lock();
5. 三种加锁总结
  1. 一锁一线程,一锁多线程问题
    使用对应锁操作对应的线程,考虑静态和非静态问题。
    同步方法和Lock锁使用
    静态是一锁多目标,非静态是一锁一目标
  2. 涉及到同步问题时,要考虑好锁对象的选择问题
    同步代码块,同步方法,Lock对象

守护线程

守护线程,也称之为后台线程。如果当前主线程GG,守护线程也GG。

守护线程一般用于:

  1. 自动下载
  2. 操作日志
  3. 操作监控

方法是通过线程对象
setDeamon(Boolean flag);
true为守护线程
false为缺省属性,正常线程

线程状态

1. 六种线程状态
状态导致状态的发生条件
NEW(新建)线程刚刚被创建,没有启动,没有调用start方法
RUNNABLE(可运行)线程已经可以在JVM中运行,但是,是否运行不确定,看当前线程是否拥有CPU执行权
BLOCKED(锁阻塞)当前线程进入一个同步代码需要获取对应的锁对象,但是发现当前的多对象已经被其他线程持有,当前线程会进入一个BLOCKED。如果占有锁对象的线程打开锁对象,当前线程持有锁对象,进入Runnable状态。
WAITING(无限等待)通过一个wait方法线程进入一个无限等待状态,这里需要另外一个线程进行唤醒操作。进入无限等待的线程是无法自己回到Runnable状态,需要其他线程通过notify或者notifyAll方法进行唤醒操作
TIMED_WAITING(计时等待)当前线程的确是等待状态,但是会在一定时间之后自动回到Runnable状态,例如 Thread.sleep() 或者是Object类内的wait(int ms)
TERMINTATED(被终止)因为Run方法运行结束正常退出线程,或者说在运行的过程中因为出现异常导致当前的线程GG
2. TIMED_WAITING(计时等待)

Thread.sleep(int ms);
在对应的线程代码块中,当前线程休眠指定的时间。
Object类内 wait(int ms)
让当前线程进入一个计时等待状态
1. 规定的时间及时完毕,线程回到可运行状态
2. 等待时间内,通过其他线程被notify或者notifyAll唤醒

sleep方法
1.调用之后休眠指定时间
2.sleep方法必须执行在run方法内,才可以休眠线程
3. sleep不会打卡当前线程占用的锁对象

在这里插入图片描述

3. BLOCKED锁阻塞

线程中有锁存在,线程需要进入带有锁操作的同步代码。如果锁对象被别人持有,只能在锁外等待

锁阻塞状态的线程是否能够抢到锁对象有很多因素
1. 优先级问题,非决定因素
2. CPU执行概率问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值