Java中的多线程

1. 线程与进程

进程就是运行中的程序,多个进程的内部数据和状态是完全独立的,多线程则共享一块内存空间和一组系统资源,彼此之间可能会有相互影响。
线程自己本身的数据只有寄存器数据和程序执行时使用的堆栈,因此对线程进行切换比进程切换的代价要小。

单线程

当java程序运行时,会自动产生一个线程,主方法main就在这个主线程上运行。

多线程

多线程指的是可以在单个程序中运行多个线程来执行不同的任务。

多线程的目的

最大限度的利用CPU资源,当一个线程需要和I/O打交道,不需要CPU的时候,让其他需要CPU资源的线程有机会获得资源,提高CPU利用率。

多任务处理

多任务处理被所有的现代操作系统所支持,有两种实现方式,一个是基于线程的,一种是基于进程的

  • 基于进程的多任务处理。进程是一个执行单位,可以使你的计算机同时运行两个以上的进程。例如既能够播放音乐,又能够同时进行文档处理。
  • 基于线程的多任务处理。线程是最小的执行单位,一个程序可以同时执行两个或以上的功能
多线程与多进程的区别

多线程比多进程需要更少的管理费用

  • 进程是重量级选手,需要分配给他们独立的地址空间。进程间的通信是昂贵的受限的,进程之间的切换也是花费不小的。
  • 线程是轻量级的选手,它们共享相同的地址空间且分享同一个进程。线程之间的通信是便宜的,切换也是低成本的。

2.Java中线程的实现

线程的两种实现方式

java中通过run方法为线程指明要完成的任务,有两种技术为线程提供run方法

  • 继承Thread类并重写run方法
  • 通过定义实现Runnable接口的类而实现run方法

注: start()方法是启动线程的唯一方法,start方法为线程的执行准备好系统资源,然后再去调用run方法。如果直接调用了run方法,它就会直接运行run方法,而不会作为一个线程来运行。并且It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.

Thread常用的构造器

1.在未指定线程名字的时候,会自动的为线程生成名字,可以使用getName()方法得到线程的名字。使用这种方法创建线程的时候,需要重写Thread的run方法,因为原来run方法什么也没有。
在这里插入图片描述
2.和第一种方法是类似的,区别是它对线程的名字进行了指定
在这里插入图片描述
3.当参数runnable不为空的时候,Thread的实例将会调用Runnable对象的run方法
在这里插入图片描述
4.与3类似,只不过指定了线程的名字。
在这里插入图片描述

线程的生命周期
一个线程从创建到消亡的过程

线程的生命周期可分为四个状态:
1.创建状态
当用new创建一个新的线程对象时,该线程处于创建状态。处于创建状态的线程只是一个控的线程对象,系统不为它分配资源。
2.可运行状态
执行线程的start()方法将为线程分配可用的系统资源,安排其运行,并调用run方法,这样线程就处于可运行状态(Runnable)。线程也许没有被运行。
start()方法启动后,是可运行状态,只有获得了CPU的资源后才会变成运行状态(running)
3.不可运行状态
当线程遇见下面的情况,处于运行状态(Running)的线程会转入不可运行状态

  • 调用了sleep()方法
  • 线程调用wait方法等待特定条件满足
  • 线程输入/输出阻塞

返回可运行状态:

  • 处于睡眠状态的线程在指定的时间过去后
  • 如果在等待某一条件,另一对象必须通过notify()或notifyAll()方法通知等待线程条件的改变
  • 如果线程是因为输入/输出阻塞,等待输入/输出完成

4.消亡状态
当线程的run方法执行结束后,该线程自然消亡。
停止线程的方式:不能使用Thread类的stop方法来终止线程的执行。一般要设定一个变量,如果满足条件则继续执行,否则跳出循环,线程结束。
在这里插入图片描述

线程的优先级

优先级高的线程将优先执行,线程的优先级是1-10的正整数。
1 - MIN_PRIORITY
10-MAX_PRIORITY
5-NORM_PRIORITY

一个线程的优先级设置遵从以下原则:

  • 线程创建时,子类继承父类的优先级
  • setPriority()可以对优先级进行设置

线程的调度策略:

  • 线程体调用yield方法,让出对CPU的占用
  • 调用了sleep()方法,使线程进入睡眠
  • 由于I/O操作而受阻塞
  • 另一个更高优先级的线程出现
  • 在支持时间片的系统中,该线程的时间片用完

多线程的同步

多线程环境中,可能有两个甚至更多的线程试图同时访问一个有限的资源。
解决方法:在线程使用一个资源时为其加锁即可。访问资源的第一个线程为其加上锁以后,其他线程不能再使用那个资源,除非被解锁。
1.Synchronized修饰方法
当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。当线程访问这个方法的时候,会给调用方法的对象上锁,只有方法结束或者出现异常的时候,锁才会解开,其他线程才可以访问。
java中每个对象都有一个锁(lock)或者叫做监视器(monitor),当访问某个对象的synchronized方法时,表示将该对象上锁,此时其他任何线程都无法再去访问该synchronized方法了,直到之前的那个线程执行方法完毕后或者抛出异常,那么将该对象的锁释放掉,其他线程才有可能再去访问该synchronized方法。
synchronized修饰static方法的时候,是对这个类的class对象进行上锁。

2.Synchronized修饰代码块
synchronized(object){
}
synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法,synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内,synchronized块之外的代码是可以被多个线程同时访问到的。
在这里插入图片描述
3.怎么实现同步?
线程间的相互作用:

  • 生产者和消费者问题
  • 哲学家就餐问题
    可能引起的问题:死锁
    Object类中的wait()
    它是final方法,不能被重写,只能被锁的拥有者调用这个方法,方法调用以后,会释放锁,直到有人通过notify()或notifyAll()方法来唤醒它
    在这里插入图片描述
    2.notify()方法
    也是一个final方法,不能被重写,必须被锁的拥有者来调用
    在这里插入图片描述
    wait与notify的总结
    在这里插入图片描述
    在这里插入图片描述
    3.另一个暂停线程运行的sleep()方法
    它会导致线程睡眠一定的时间,但是不会释放掉锁。
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值