java多线程

多线程

进程和线程

进程 系统资源分配的最小单位

进程是指程序动态执行一次的过程,程序执行后在内存中开辟一块空间,在计算机系统中被操作系统所管理

线程 CPU调度的最小单位

进程在执行过程中会产生多个线程,线程之间相互协作完成程序各个功能

并发和并行

并发 事件之间交替进行

如果只有一个CPU,在同一时刻各个线程不能同时抢占到CPU的资源,使线程交替进行

在只有单个CPU处理时,线程以某种顺序执行,就叫线程调度

java中的线程调度方式为抢占式调度 优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性)

并行 事件同步进行

多CPU条件下,线程之间不抢占一个CPU资源,可以实现同步进行

线程的分类

用户线程(主线程main和子线程) 子线程需要手动创建

守护线程 GC线程

线程的创建

继承Thread(重写run方法)

线程执行流程

继承Thread并重写run方法,这个方法就是该线程对象执行的具体方法

在main方法中实例化线程对象

调用Thread类的start方法执行线程方法而不是直接run 执行run方法等于调用方法 而执行start方法才会真正创造线程

public class HelloThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("线程"+i+"正在执行");
        }
    }

    public static void main(String[] args) {
        HelloThread thread = new HelloThread();
        thread.run();
        for (int i = 0; i < 1000; i++) {
            System.out.println("主线程"+i+"正在执行");
        }
    }
}

静态代理模式

实体与代理都实现一个接口,这个接口提供他们的共同方法

实体有个别方法不通过实体直接调用,而通过代理来实现,实体把精力专注在独有的方法上

而这些个别需要代理来实现的方法是代理有准备的而且是一类实体共同需要实现的方法

代理需要做的是,在代理类中定义实体类实例,在代理类构造方法中传入实体类实例来实现实例初始化

代理类中执行他们的共同方法,在方法内调用实体实例的该共同方法

在main方法中实例化代理并调用该共同方法时就相当于实体执行共同方法

class Pojo implements A{
    @override
    together(){      //实体
        ********
    }
}
    
class Broker implements A{     
    private Pojo pojo;          //代理
    public Broker(Pojo pojo){
        this.pojo = pojo;
    }
    
    @override
    together(){
       	this.pojo.together();
    }
}
 public static void main(String[] args) {
	Broker broker = new broker(new pojo());
    broker.together();
 }   

实现Runnable接口(重写run方法)

执行流程 静态代理模式

实现Runnable接口并重写run方法

在main方法中实例化该线程对象

实例化Thread对象,把线程对象传进去

Thread对象执行start方法

public class RunnableDemo implements Runnable{

    private int ticketNum = 10;

    @Override
    public void run() {
        while (true) {
            System.out.println("线程" + Thread.currentThread().getName() + "正在拿第"+(ticketNum--)+"张票");
            if (ticketNum<=0){
                break;
            }
        }
    }

    public static void main(String[] args) {
        RunnableDemo runnableDemo = new RunnableDemo();
        Thread thread1 = new Thread(runnableDemo,"A用户");
        Thread thread2 = new Thread(runnableDemo,"B用户");
        Thread thread3 = new Thread(runnableDemo,"黄牛");
        thread1.start();
        thread2.start();
        thread1.start();

    }
}

实现Callable接口(重写call方法)

重写call方法 有返回值 可抛出异常

线程的生命周期

新生 new线程时诞生

就绪 start时进入就绪状态

运行 CPU调度开始运行

阻塞 调用sleep、wait或同步锁定

消亡 线程进入死亡状态不可以再次启动

等待 join等待

等待多久的等待 join等待 join(1000)

线程状态方法

线程休眠

sleep 进入阻塞状态,不释放锁

线程调用sleep方法会返回阻塞状态,以sleep方法限定的时长在阻塞状态等待,不影响其他进程,但是他拿的锁不会随休眠释放

线程礼让

yield 让当前本被CPU调度的线程返回就绪状态,和其他线程一起等待调度

礼让之后线程处于同一水平线,就是就绪状态,后续谁先被调度无法决定

线程强制执行

join 优先执行,其他线程等待

线程调用join方法会优先执行该线程,其他线程进入等待状态

观测线程状态

Thread.State

State 是线程的一个静态成员

可以通过get来取当前线程的状态

线程优先级

Priority

默认提供三种优先级

MAX_PRIORITY = 10

MIN_PRIORITY = 1

NORM_PRIORITY = 5

可以通过get来取当前线程的优先级 set来定义线程的优先级 范围1-10

线程的优先级只能在宏观上定义线程的权重不同,但是不一定一定优先,CPU实际调度为主

守护线程

GC线程

线程分为用户线程和守护线程

守护线程指不需要虚拟机等待完成的维护用户线程的独特线程 虚拟机需要等待用户线程完成

显式定义线程为守护线程可以

Thread.setDaemon(true) 默认为false用户线程

当用户线程死亡后守护线程会在很短的时间死亡 用户线程死亡之后可能守护线程还在工作很短时间

线程同步

当多个线程对一个共同事件进行操作时引发并发问题,就需要线程同步

解决办法:队列+锁

线程排队不同时争夺资源

拿到锁才可以操作共同事件,一个线程对象一把锁,操作完成释放锁,接下来的线程拿到锁

Synchronized的应用

Synchronized 非静态同步方法 创建的锁是对象锁,指当前类this的实例

Public Synchronized void buy()

对于一个类的实例,非静态同步方法用的是同一个锁,即这个对象的锁,对象的锁只有一个

所以当一个线程在拿到该对象的锁之后,在释放锁之前,其他线程都无法执行

这个锁是对象锁,针对的是这一个实例对象,该对象的其他非静态同步方法必须等待当前上锁的非静态同步方法执行完毕才能获得锁

Synchronized 静态同步方法

Public Static Synchronized void buy()

对于一个类,静态同步方法上锁之后,这个类的所有实例对象的静态同步方法都要等待

静态同步方法和非静态同步方法用的是不同的锁,互不影响

非静态方法影响当前对象其他非静态方法,不影响其他对象

静态方法影响所有实例对象的静态方法

Synchronized 同步块

同步方法中可能存在很多只读的无需同步的代码,锁会浪费资源,而锁大量的只读代码浪费资源

可以用来锁住共享资源,即公共修改内容

对于Synchronized的总结

静态同步方法和非静态同步方法用的是不同的锁,互不影响

非静态方法影响当前对象其他非静态方法,不影响其他对象

静态方法影响所有实例对象的静态方法

死锁

线程之间拿到对方需要的锁且双方都不释放

有锁仍要别人的锁容易发生

Lock锁

显示定义同步锁,上锁和释放锁看的到

经常使用它的子类

可重入锁ReentrantLocK

ReentrantLocK lock = new ReentrantLocK();
lock.lock();
lock.unlock();

线程通信

线程之间相互协作完成需求

object类的方法

notify() 唤醒随机一个等待线程

notifyAll() 唤醒全部等待线程

wait() 当前线程等待,并释放锁

管程法

以中间池为基准

生产者消费者问题

池满通知,池空通知

信号灯法

以一个值为基准

值变通知

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值