day06 线程 同步 线程多线程原理1: 线程执行的随机性
CPU执行哪个线程是随机的, 不能人为干预
Java线程调度是抢占式的, 多个线程互相抢夺CPU的执行权
补充:
第一种方式: 继承Thread类
定义类继承Thread
重写run()方法, 要执行的任务
创建子类的对象, 调用start()方法启动线程
多线程原理2: 多线程的内存
多线程情况下, 每个线程都有各自的栈内存
每个线程各自的方法调用, 进的是各自线程的栈
栈是每个线程各自的, 堆是所有线程共用的
Thread常用方法: getName(), currentThread()
java.lang.Thread类: 表示线程. 实现了Runnable接口 hread常用方法: setName(), Thread(String name)
java.lang.Thread类: 表示线程. 实现了Runnable接口
// 构造方法
Thread(String threadName): 创建Thead对象并指定线程名
// 成员方法
void setName(String name): 设置线程名称
Thread常用方法: sleep()
java.lang.Thread类: 表示线程. 实现了Runnable接口
// 静态方法
static void sleep(long millis): 让所在线程睡眠指定的"毫秒" 创建多线程程序的方式2: 实现Runnable接口
创建线程的第2种方式:
1. 定义类, 实现Runnable接口
2. 重写 run() 方法
3. 创建Runnable实现类对象
4. 创建Thread类对象, 在构造方法中传入Runnable实现类对象
5. 通过Thread对象调用start()方法启动线程
java.lang.Thread类: 表示线程. 实现了Runnable接口
// 构造方法
Thread Thread(Runnable target): 通过Runnable对象创建Thread对象
Thread Thread(Runnable target, String threadName): 通过Runnable对象创建对象并指定线程名 Thread和Runnable的区别 实现Runnable的好处: 1. 避免单继承的局限性 2. 增强了程序的扩展性, 降低了程序的耦合性(解耦) 3. 线程是Thread, 任务是Runnable实现类对象. 相当于将线程和任务分离 匿名内部类方式创建线程: public class Test { public static void main(String[] args) { // 匿名内部类方式 new Thread(new Runnable(){ @Override public void run() { // 要执行的任务 } }).start(); } } 解决线程安全问题方式1: 同步代码块
解决多线程操作共享数据的安全问题的3种方式:
1. 同步代码块
2. 同步方法
3. 锁机制 同步代码块: 使用 synchronized 关键字修饰的代码块, 并传入一个当作锁的对象
格式:
synchronized (锁对象) {
// 操作共享数据的代码
}
注意:
锁对象可以是任意类型的一个对象
锁对象必须是被多个线程共享的唯一对象
锁对象的作用: 只让一个线程在同步代码块中执行 同步技术解决线程安全问题的原理
锁对象, 也称为"同步锁", "对象监视器"
同步的原理:
线程进入同步代码块前, 会争夺锁对象, 只有一个线程会抢到锁对象
进入同步代码块的线程, 会持有锁对象, 并执行同步代码块中的代码
此时同步代码块外的线程, 处于阻塞状态, 只能等待
当同步代码块内的线程执行完代码块, 会离开同步代码块, 并归还锁对象给同步代码块
等在同步代码块外的其他线程就可以继续争夺锁对象 解决线程安全问题方式2: 同步方法
同步方法: 使用 synchronized 关键字修饰的方法, 具有默认的锁对象
非静态同步方法的锁对象: this
// 非静态同步方法
public synchronized void method(){
// 可能会产生线程安全问题的代码
} 静态同步方法:
public static synchronized void method(){
// 可能会产生线程安全问题的代码
}
静态同步方法的锁对象: 当前类的字节码对象 获取一个类的字节码对象的3种方式:
1. 对象.getClass()
2. 类名.class
3. Class.forName("类的全路径"); 线程安全和效率的特点: 线程安全, 效率低,线程不安全, 效率高 线程的生命周期中, 可以出现有6种状态:
1. NEW 新建
线程被创建, 但没有调用 start() 启动
2. RUNNABLE 可运行
调用 start()方法后已启动, 但可能正在执行 run() 方法的代码, 也可能正在等待CPU的调度
3. BLOCKED 阻塞
线程试图获取锁, 但此时锁被其他线程持有
4. WAITING 无限等待
通过锁对象调用无参的 wait() 进入此状态.
等待其他线程通过锁对象执行 notify() 或 notifyAll() 才能结束这个状态
5. TIMED_WAITING 计时等待
如通过锁对象调用有参的 wait(long millis) 或 sleep(long millis), 则进入此状态.
直到时间结束之前被其他线程通过锁对象执行notify()或notifyAll()唤醒, 或时间结束自动唤醒
6. TERMINATED 终止
run()方法结束(执行结束, 或内部出现异常), 则进入此状态 Object类中wait(long timeout)和notifyAll()方法
java.lang.Object类:
// 成员方法 (只能通过"锁对象"调用)
void notifyAll(): 唤醒所有在同一个锁对象上处于等待状态的线程
void wait(long timeout): 让当前线程处于计时等待状态, 时间到或被唤醒后结束此状态
|