第十六部分 多线程

一、线程与进程

1 . 当进程进入内存运行,就编程了线程。
1.1线程有三大特性:1.独立性 2.动态性 3.并发性。

  • 独立性:每个进程都有自己的私有地址空间
  • 动态性:进程拥有自己的生命周期和不同状态
  • 并发性:多个进程在单个处理器上执行,多个进程之间互不影响

1.2并发性和并行性是两个概念:

  • 并行指的是在同一时间,多条指令在多个处理器上执行。
  • 并发性指的是同一时刻只有一条指令执行,但多个指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。

总而言之,一个程序运行后至少有一个进程,一个进程里可以包含多个线程,但至少有一个线程。
2. 多线程的优势
2.1 线程的划分尺度小于进程,所以多线程程序的并发性高。每个线程都有自己的独立内存单元,但是共享内存,从而提高了程序的运行效率。

2.2 线程与进程相互对比:

  • 线程之间共享内存,进程之间不能共享内存

  • 系统创建进程的代价大于创建线程的代价,因此多线程来实现多任务并发效率更高

  • Java内置了多线程功能支持,简化了多线程编程

  • 线程的创建与启动:
    Java使用Thread类代表线程,所有的线程对象都必须是Thread类或子类的实例。

二、线程的创建

2.1 继承Thread类创建线程类

步骤如下

extends Thread

  • 定义Thread类的子类,并重写run()方法,其方法的方法体就代表了线程需要完成的任务。因此把run()方法成为线程执行体。
  • 创建(new状态)thread实例
  • 用start启动线程
  • 线程两方法:
    • Thread.currentThread()返回当前正在执行的线程对象
    • getName()返回调用该方法的线程名字

2.2使用Runnable接口创建线程类

Implements Runnable

  • 定义Runnable接口实现类重写run方法
  • 创建(new状态)实体类对象,使用new Thread(对象,“线程名”).start();来启动多线程

3.1线程的生命周期
线程需要经过 new ready running bolcked dead 五种状态
新建 就绪 运行 阻塞 死亡五种状态

  • 新建状态(new):通过new关键字创建了一个线程后,该线程就处于新建状态

  • 就绪状态(start用来启动线程):new状态下的线程通过.start()进入就绪状态

  • 运行状态(running):调用run()方法,进入运行状态
    另有 - 使用yield()方法可使运行状态的线程进入就绪状态。
    所有现代桌面和服务器都采用抢占式调度策略,但小型设备如手机则可能采用协作式调度策略。在这样的系统中,只有当一个线程调用了sleep()或yield()方法后才回房企所占用的资源——也就是必须由该线程主动放弃所有占用的资源。

  • 阻塞状态(blocked):

    • sleep()主动放弃所占用的处理器资源
    • 调用了阻塞式IO方法
    • 线程试图获得一个同步监视器
    • 线程在等待某个通知(notify())
    • 线程调用了suspend()方法将该线程挂起,易导致死锁,尽量避免使用
      • 当:
    • sleep()超时
    • IO方法已经返回
    • 线程成功获得了同步监视器
    • 收到了通知
    • 挂起状态的线程调用了resume()恢复方法的时候,会从阻塞状态恢复就绪状态。
  • 死亡状态(dead):有三种形式

  • run()或call()方法执行完毕后

  • 线程抛出一个未捕获的Exception或Error

  • 使用stop()方法来结束线程——易导致死锁,不推荐使用

为了测试某个线程是否已经死亡,可以调用线程对象isAlive()方法,当线程出于start,running,blocked三种状态时候,该方法返回true。若处于就绪或死亡状态,则返回false。

注:run()是一个普通发放,不是线程执行体

三、控制线程

1.join线程【我理解为“加塞儿”的,插队干活】
Thread提供了让一个线程等待另一个线程运行完成的方法——join()方法
某个程序在执行过程中调用了其他线程的join方法,调用线程将会阻塞,直到被join加入的线程执行完为止。
join()
join(long milils)可设定插队执行的时间 若插队时间过了,别的线程就不等他了
join(long millis,int nanos)最长插队时间毫秒,增加插队nanos毫微秒
2.后台线程
有一种线程,它在后台运行,任务是为其他的线程提供服务。被称为后台线程或守护线程,精灵线程。
后台线程特征:如果所有前台线程都死亡,后台线程会自动死亡。
在这里插入图片描述
调用Thread对象的setDeamon(true)可设置线程为守护线程。
还可以通过Thread类提供的isDeamon()方法判断是否为守护线程。

3.睡眠线程
3.1 如果想让正在进行的线程暂停一会儿,并进入阻塞状态,可执行sleep()方法。

  • sleep(long millis):让当前正在执行的线程停止millis毫秒
  • sleep(long millis,int nanos)暂停时间毫秒,增加nanos毫微秒

Thread还提供了yield()静态方法,它也可以让正在执行的线程暂停,但不会阻塞该线程,将线程状态转至就绪状态。

3.2 sleep与yield方法区别

  • sleep方法暂停当前线程后,会给其他线程执行机会,不会考虑优先级。而yield方法只会给优先级相同的机会。
  • sleep方法执行后进入阻塞状态,阻塞时间过了在转换为就绪状态。而yield不会将线程转入阻塞状态,而是强制进入就绪状态。
  • sleep方法抛出了InterruptedException异常。而yield方法没有。
  • sleep方法具有更良好的移植性,不建议使用yield方法。

4.改变线程优先级
每个线程执行都具有一定的优先级,高优先级的线程获得更多执行机会。
Thread提供了setPriority(int newPriority) 和getPriority()方法来设置和返回指定线程的优先级。1-10
MAX_PRIORITY 是10
MIN_PRIORITY 是1
NORM_PRIORITY 是5

四、线程同步

1.线程安全问题没细看
synchrinized代码块 或 修饰方法没细看
同步锁lock没细看

死锁:
连个线程互相等待对方释放同步监视器时就会产生死锁,java虚拟机没有监测,也没有采取措施来处理死锁的情况,所以多线程编程时应采取措施避免死锁出现。一旦出现死锁,不会发生异常,没有提示,只是所以线程处于阻塞状态,无法继续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值