Java多线程相关要点

多线程 同步

1.多线程

1.1多线程的优缺点

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

1.2 创建自定义线程类的两种方式

class Thread类 Java中的一个线程类
Thread类是Runnable接口的实现类,同时提供了很多线 程的操作使用的方法。
interface Runnable接口 这里规定了what will be run? 里面只有一个方法 run方法
方式一: 自定义线程类,继承Thread类,重写run方法
创建自定义线程对象,直接调用start方法,开启线程
方式二: 自定义线程类,遵从Runnable接口
使用自定义遵从接口Runnable实现类对象,作为Thread 构造方法参数
借助于Thread类对象和start方法,开启线程
【推荐】 以上两种方式,推荐使用方拾二,遵从Runnable接口来 完成自定义线程,不影响正常的继承逻辑,并且可以使用匿名 内部类来完成线程代码块的书写

1.3Thread类中的方法

构造方法 Constructor
Thread(); 分配一个新的线程对象,无目标,无指定名字
Thread(Runnable target); 创建一个新的线程对象,并且在创建线程对象的过 程中,使用Runnable接口的实现类对象作为执行的线程代码块目标
Thread(String name); 创建一个新的线程,无指定目标,但是指定当前线 程的名字是什么
Thread(Runnable target, String name); 创建一个线程的线程对象,使用Runnable接口实现 类对象,作为执行目标,并且指定name作为线程名
成员方法:
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类调用,获取当 前所处代码块对应的线程对象。

2.线程安全问题和解决方案

2.1共享资源问题 用静态成员变量来保存

2.2资源冲突问题

 加锁:
1.同步代码块
2.同步方法
3.Lock
2.2.1同步代码块

特征:

  1. synchronized 小括号里面的对象是锁对象,并且要 求如果是多线程的情况下,锁对象必须是同一个对象。
  2. synchronized 大括号中的代码块就是需要进行同步 的代码,或者说是加锁的代码,大括号里面的内容,有且只允 许一个线程进入。
  3. 同步代码块越短越好,在保证安全的情况下,提高性能

问题: 1. 目前锁对象感觉很随意,存在一定的隐患 2. 代码层级关系很复杂,看着有点麻烦

2.2.2同步方法

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

  1. 静态成员方法 锁对象,是当前类对应的字节码文件.class 类 名.class
  2. 非静态成员方法 锁对象就是当前类对象 this
    选择同步方法是否使用static修饰问题
  3. 如果非static修饰,要保证执行的线程对象有且只有 一个,因为锁对象就是当前线程对 象
  4. 如果是static修饰,锁对象具有唯一性,多个线程使 用的锁是同一个锁。
2.2.3Lock锁

Java提供了一个对于线程安全问题,加锁操作相对于同步代码 块和同步方法更加广泛的一种操作方式。

  1. 对象化操作。 创建Lock构造方法 Lock lock = new ReentrantLock();
  2. 方法化操作。 开锁: unlock(); 加锁: lock();

2.3三种加锁方式总结

  1. 一锁一线程,一锁多线程问题。 使用对应的锁操作对应的线程,考虑静态和非静态问题。 同步方法和Lock锁使用。 静态是一锁多目标,非静态是一锁一目标
  2. 涉及到同步问题时,要考虑好锁对象的选择问题 同步代码块,同步方法,Lock对象。
  3. 守护线程
    守护线程,也称之为后台线程,如果当前主线程挂了,守护线程也就G挂了。
    守护线程一般用于: 1. 自动下载 2. 操作日志 3. 操作监控
    方法是通过线程对象
    setDeamon(boolean flag);
    true为守护线程 false缺省属性,正常线程

4.线程状态

状态 导致状态的发生条件
NEW(新建) 线程刚刚被创建,没有启动,没有调 用start方法
RUNNABLE(可运行) 线程已经可以在JVM中运行,但是是 否运行不确定,看当前线程是否拥有 CPU执 行权
BLOCKED(锁阻塞) 当前线程进入一个同步代码需要获取 对应的锁对象,但是发现当前锁对象 被其他线 程持有,当前线程会进入一 个BLOCKED。如果占用锁对象的线 程打开锁对象,当 前线程持有对应锁 对象,进入Runnable状态

WAITING(无限等待) 通过一个wait方法线程进入一个无限 等待状态,这里需要另外一个线程进 行唤醒操 作。进入无限等待状态的线 程是无法自己回到Runnable状态,需 要其他线程通过 notify或者notifyAll 方法进行唤醒操作

TIMED_WAITING(计 时等待) 当前线程的确是等待状态,但是会在 一定时间之后自动回到Runnable状 态,例如 Thread.sleep() 或者是Object 类内的wait(int ms);
TERMINATED(被终 止) 因为Run方法运行结束正常退出线 程,或者说在运行的过程中因为出现 异常导致当 前线程GG思密达

4.1计时等待状态

Thread.sleep(int ms); 在对应线程代码块中,当前线程休眠指定的时间。 Object类内 wait(int ms); 让当前线程进入一个计时等待状态

  1. 规定的时间及时完毕,线程回到可运行状态 2. 在等待时间内,通过其他线程被notify或者 notifyAll唤醒
    Sleep方法
  2. 调用之后休眠指定时间 2. sleep方法必须执行在run方法内,才可以休眠线程 3. sleep不会打卡当前线程占用的锁对象。

4.2BLOCKED(锁阻塞) 状态

线程中有锁存在,线程需要进入带有锁操作的同步代码,如果 锁对象被别人持有,只能在锁外等待
锁阻塞状态的线程是否能够抢到锁对象有很多因素 1. 优先级问题,非决定因素 2. CPU执行概率问题。
后期高并发一定会存在多线程操作锁对象问题,秒杀,抢 购… 队列方式来处理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值