Notes18 day18 多线程

day18 多线程

并发

指两个或多个事件在同一个时间段内发生。

并行

指两个或多个事件在同一时刻发生(同时发生)。

进程

概述

是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。

简述

就是正在运行的程序

意义

可以提高CPU的使用率

线程

概述

是程序的执行单元,执行路径。是程序使用CPU的最基本单位。

意义

不是提高程序的执行速度。其实是**为了提高应用程序的使用率

单线程

如果程序只有一条执行路径

多线程

程序有多条执行路径

线程调度

分类

分时调度、抢占式调度

多线程创建

继承Thread类

创建步骤

  1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。

  2. 创建Thread子类的实例,即创建了线程对象

  3. 调用线程对象的start()方法来启动该线程

常用方法

setName()、getName()

实现Runnable接口

创建步骤

1.定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

2.创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

3.调用线程对象的start()方法来启动线程。

常用方法

setName() 给Thread对象set设置名字

Thread.currentThread() 可以用在实现Runnable的类中,获取当前线程的名字

也可以通过有参构造来给Thread对象直接设置名字

Thread类和Runnable接口的区别

1.Runnable接口的话,可以避免单继承的局限性,具有较强的健壮性。
​
2.Runnable可以实现资源的共享,同时处理同一资源。
​
3.Thread类的线程间都是独立运行的,资源不共享。
​
4.继承Thread类不再被其他类继承(java不存在多继承)
​
​

线程状态

 

线程调度

线程休眠

public static void sleep(long millis) 停顿一会再走

设置线程优先级

public final void setPriority(int newPriority)

更改线程的优先级。默认为5, 最小级别:1 ,最大级别:10

注意:只是尽量保持按照分配的级别进行调度,但也不一定会按照该设置调度

线程的加入

public final void join():等待该线程终止。

先把加入的这个线程走完(终止)然后其他的线程自已去抢

注意:只是尽量让调用者尽量先执行,但也不保证。

线程礼让

public static void yield():暂停当前正在执行的线程对象,并执行其他线程。

让多个线程的执行更和谐,但是不能靠它保证一人一次。

线程守护

public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。

当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。

线程停止

* public final void stop():让线程停止,过时了,但是还可以使用。和下面解释是一样的,有个小区别:若无阻塞正常运行,若有阻塞,则第一次扫描到的阻塞后面的代码不再运行,也不会报错。

* public void interrupt():中断线程。 把线程的状态终止,并抛出一个InterruptedException。 解释:就是执行到该方法,然后进入到调用该方法的线程执行体里面(但是执行该方法不影响该方法此时所在线程正常往下运行,从此时开始他们两个相当于一个并行),从调用该方法的线程体中 此时线程执行到的位置往后开始扫描,若是后面没有阻塞的话正常执行,不用报错,若是后面有多个地方阻塞,则只需跳过第一次阻塞,并抛出异常,继续执行后面代码,后面阻塞正常阻塞

线程的生命周期

新建 --- 就绪 ---  运行 --- 死亡 
新建:创建线程对象
就绪:有执行的资格,没有执行权
运行:有执行的资格,有执行权
阻塞:由于一些操作让线程处于该状态。没有资格,没有执行权而另一些操作却可以把它激活,激活后处于就绪状态
死亡:线程对象变成垃圾,等回收

 

线程安全

多线程执行的结果和单线程运行的结果是一样的,就是线程安全的

实现Runnable接口的线程安全问题

为了保证每个线程都能正常执行原子操作,Java引入了线程同步机制。

  • 实现同步的方式

  • ==同步代码块==

  • ==同步方法==

  • ==Lock锁==

同步代码块

格式
synchronized(同步锁的对象){  //可以是任意类型的对象
    需要同步操作的代码 
}
注意
  • 锁对象 可以是任意类型对象。

  • 多个线程对象 要使用同一把锁。

同步方法

非静态同步方法、静态同步方法

非静态同步方法

格式
public synchronized void method(){
    可能会产生线程安全问题的代码 
}
注意

该锁对象就是 该类的对像 教案举的例子解释 本质是用同步代码块举例的,同步代码快的本质是 任意类型的对象或者类.class

实现Runnable接口类中 同步非静态方法,调用的共享资源和使用锁 可以不是静态的但一定是同一个

静态同步方法

格式
public synchronized static void method(){
    可能会产生线程安全问题的代码 
}
注意

静态同步方法 他的共享资源是静态的

和非静态同步锁区别(一个是对象锁,另外一个是Class锁) 总之 就是 当前类.class

因为在静态方法中,所以教案上用同步代码块解释的锁也必须是静态的,可以是对象也可以是类.class 但若是对象对象必须是静态的

Lock锁

更广泛的锁定操作, 同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象

Lock接口提供的方法
方法名说明
public void lock()加同步锁。
public void unlock()释放同步锁。
注意

使用该方法前 应先创建此锁对象 Lock l = new ReentrantLock();

创建Lock对象可以不是静态的,除非用在静态同步方法中

最后一定要释放此锁,一般用finally来实现

小结

用实现接口的形式 它的共享资源和锁 除非在静态同步方法中使用,才会设置静态,在其他同步方法和同步代码块中一般不用静态

继承Thread类安全问题

注意

锁和共享资源可以是静态的 若不是静态的得确保他们是分别是同一个

同步代码块

注意

锁对象是 类名.class 或者 其他类对象 且要注意该类对象要是共用的,所以要设成静态 不能用this

同步方法

注意

只有静态同步方法

其实与同步代码块的一样 锁对象是 类名.class 或者 其他类对象 且要注意该类对象要是共用的也就一同一个,因为在静态方法中所以要设成静态 不能用this

lock锁

注意

创建的lock锁对象可以是静态的,要不然就是同一个,若不设置成静态的不能用在静态同步方法中

注意

      1、是否有共享资源      是
      2、是否有多条执行路径     是
      3、是否这多条执行路径操作共享资源   是
​
      满足以上3种条件,就会出现线程安全问题

同步的好处和弊端

同步的好处:
   同步的出现解决了多线程的安全问题
   
同步的弊端:
    当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
​
回顾: 线程安全,效率低

死锁

简单理解:指两个线程或多个线程相互持有对方所需要的资源,导致线程都处于等待状态,无法往下执行,这就是死锁!

如何解决死锁

死锁的出现主要是因为同步中嵌套同步了,我们只需要保证不让它们进行嵌套即可解决死锁的出现!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值