JUC–基础

线程简介

多任务

同一时间做了一件事情,交替很快,宏观上是同时。(边玩手机边吃饭

多线程

一个车道堵住,多开车道

一个进程可以有多个线程,比如视频里面同时有声音,弹幕,图像

程序是一个静态概念。进程是一个动态概念。线程是CPU调度和执行的单位。

  • 线程是独立的执行路径。
  • 对同一个资源进行操作时,要加入并发控制。
  • 数据同步问题
  • main()是主线程,系统的入口

线程创建

继承ThreadClass类:

*重写run方法,调用start开启线程。线程开启不是立即执行,由CPU进行调度。并行交替执行。

*多线程下载图片:理想路径t1-t2-t3。最终路径 3-1-2 同时下载的。看谁小谁先下完。并不是顺序执行。(有参数)

*不建议使用:避免OOP单继承局限性

实现Runnable接口(本质)(推荐使用)

*实现runnable接口A,重写run方法,执行线程需要将丢入runnable接口

new Thread(testThread3).star();

*推荐使用:灵活,方便同一个对象被多个线程使用

实现Callable接口

1.定义返回值

2.可以抛出异常

创建执行服务,提交执行,获取结果,关闭服务

线程并发问题

同时拿到一张票的问题。

静态代理模式

例如:结婚的婚庆公司

Interface Marry

两个实现:真实角色和代理角色,代理角色在方法重写里面对目标对象(you)进行操作。真实对象和代理角色都会去实现marry接口。一个只管结婚,一个管所有所做的杂事。只需创建一个真实对象作为参数传入代理对象实现的方法。

与多线程的方法:

  • Thread类相当于代理对象WeddingCompany
  • 代理的是真实对象runnable接口
  • happymarry()相当于star

核心代码

*帮助你实现你本身的run方法

Lambda表达式

函数式编程,为了简化

理解函数式接口Functional Interface:

  • 任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口
  • 对于函数式接口,我们可以通过lambda表达式来创建该接口的对象
public interface Runnable{
    public abstract void run();
}

在外面的一个新的对象,实现这个接口,重写它的方法再调用很冗长。

简化过程:实现–>静态内部类–>局部内部类–>匿名内部类

最终:lambda表达式

//lambda
like = () ->{
     System.out.println("i like lambda5 ")
};
like.lambda();

线程状态

状态

创建状态–(启动)–>就绪状态<==获得/释放CPU资源==>运行状态(自然执行完毕/外部干涉终止)死亡状态

运行状态(输入休眠等)–>阻塞状态(阻塞解除)–>就绪状态

线程一旦创建就进入到新生状态

调用star之后进入就绪状态

  • 设置线程优先级 setPriority(int newPriority)
  • 指定毫秒数内让当前执行的线程休眠 static void sleep(long millis)
  • 等待该线程终止 void join()
  • 暂停当前正在执行的线程对象并执行 其它线程 static void yield()
  • 中断线程,别用! void interrupt()
  • 测试线程是否处于活动状态,别用! boolean isAlive()

线程停止

推荐使用一个标志位进行终止变量,当flag=false,则终止线程运行。

手写线程停止,改变标志为的状态。

线程休眠

  • 每个对象都有一个锁,sleep不会释放锁(线程同步
  • sleep可以模拟网络延时:放大问题发生性
  • 模拟倒计时 获取当前时间

线程礼让yield

礼让不一定成功

Thread.yield();

JOIN合并线程

先执行此线程,有点像插队。其它线程都阻塞了。

线程状态观测

Thread.State state=thread.getState();

在不同代码位置加上以上代码可以观测线程状态

*线程只能启动一次,线程终端或者结束,一旦进入死亡状态,就不能再次启动

线程优先级

priority 越高越先(!!!不一定(优先级默认是5

有作用但不是每次都,只是大多数

*优先级的设定建议在star()调度前

守护线程daemon

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

  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 如,后台记录操作日志,监控内存,垃圾回收等待

线程同步

多个线程操作同一个资源

同一个资源,多人使用:排队

并发问题,修改,线程同步。被修改对象的等待池形成队列,等待前面的线程使用完毕

撤硕:🈶人,有锁

线程同步:队列+锁

*独占问题

同步方法及同步块

private:对象只能被方法访问

synchronized:

  • 方法:粒度大,线程阻塞,独占锁问题,影响效率
  • 块:synchronized(Obj){}

分析:修改代码才需要同步,只读代码不需要加锁

*难点:锁的对象(变化的量 银行/银行里的钱)

CopyOnWriteList

JUC.concurrent下的

测试JUC安全类型的集合

死锁

都在等待对方释放资源。

产生的必要条件:

  • 互斥条件:一个资源每次只能被一个进程使用
  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
  • 不剥夺:线程已获得的资源,在未使用完之前,不能强行剥夺
  • 循环等待:若干进程之间形成一种头尾相连

Lock锁

  • 显示锁,需要手动开关
  • 只有代码块锁
  • 性能更好。JVM调度

可重入锁

线程协助

生产者消费者模式

并发协作模型:管程法(数据缓存区)、信号灯法

管程法

生产者、消费者、产品、缓冲区

//消费者
//产品
//缓冲区

信号灯

给一个flag,标志位解决

线程池

创建线程


评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Translate »