zoukankan      html  css  js  c++  java
  • JAVA基础知识总结:十八

    一、进程和线程
    1.进程
    是一个程序的运行状态和资源占用的描述

    进程的特点:
    a.独立性:不同的进程之间是独立的,相互之间资源不共享
    b.动态性:进程在系统中不是静止不动的,而是一直活动的
    c.并发性:多个进程可以在同一个处理器上同时进行,互不影响

    多进程:一个操作系统可以运行多个应用程序

    2.线程
    线程是进程的组成部分,一个进程可以有多个线程,每个线程用来处理一个指定的子任务

    举例:打开酷狗软件-------》这是一个进程
    播放歌曲/刷新歌词------》两个线程(并发的)

    线程的执行是抢占式的,多个线程可以在一个进程中并发执行,其实质是CPU在不同的线程之间进行快速的切换,也就是说,当前运行的线程在任何时候都有可能被挂起,以便于别的线程去执行对应的任务,同样的,被挂起的线程随时有可能争抢到时间片,继续执行

    多线程:在一个进程中,多个线程同时进行
    应用:一个浏览器可以同时下载多张图片
    一个服务器可以同时响应多个用户请求


    3.进程和线程之间的关系
    a.一个程序运行后至少有一个进程
    b.一个进程可以包含多个线程,但至少需要有一个线程,否则进程是没有意义的

    为什么要选用多线程编程而不选用多进程呢?/线程相对于进程的优点?
    a.进程间资源不能进行共享,但是线程之间可以共享资源
    b.系统如果要创建进程的话,需要为这个进程重新分配系统资源,而创建线程的话则相对容易的多,因此使用线程处理并发任务比进程的效率高
    c.Java中内置了多线程的功能支持,简化了多线程编程


    二、线程的实现
    1.继承自Thread类
    Thread类是所有线程类的父类,实现了对线程的抽取和封装
    1>使用Thread类创建并开启线程的步骤:
    a.定义一个类,继承自Thread类,重写该类的run方法,该run方法的方法体就代表了线程需要完成的任务,因此,run方法体也被称为线程执行体
    b.创建子类的对象,即相当于创建了一个线程
    c.需要使用start方法手动开启线程


    关于线程的执行,需要注意的问题:
    a.如果一个线程中的所有的任务都处理完了,那么这个线程会自动停止(正常情况)
    b.如果在一个线程a中开辟了子线程a0,a1,a2.....那么线程a停止后,在这个线程中开辟的子线程会全部停止
    c.多个线程并发执行,其实就是在争抢CPU时间片


    2.实现接口Runnable
    使用实现Runnable接口的方式创建并开启线程的步骤:
    a.定义一个类,这个类实现Runnable接口,需要重写对应的run方法,run方法的方法体同样是线程的执行体
    b.创建实现了Runnable接口对应类的对象,并以此实例作为Thread类的target对象
    c.手动调用start方法开启线程

    两种方式实现线程的比较:
    1.实现Runnabel接口
    a.自定义的类只是实现了Runnable接口,同时还可以去继承其他的类
    b.多个线程可以共享同一个target对象,所以非常适合多个相同的线程来处理同一份资源的情况
    弊端:不直观,如果要获取当前正在运行的线程,只能通过Thread.currentThread()
    2.继承Thread类
    直观,如果要访问正在运行的线程,除了可以通过Thread.currentThread()方式之外,还可以使用super关键字

    弊端:因为线程类已经继承了Thread类,所以不能再去继承其他的类(单继承)


    实际上,大多数的多线程应用都采用实现Runnable接口的方式实现(推荐使用匿名内部类)


    三、线程的生命周期
    对象的生命周期:从一个对象被实例化到这个对象被销毁的过程中,这个对象经历的种种状态

    举例:人的生命周期:出生---婴儿---儿童---少年---青年----中年---老年---死亡


    对于线程,当一个线程被创建并启动之后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,在线程的生命周期中,同样的也会经历各种过程(在一个进程中,多个线程可以并发,争抢CPU时间片)


    New(新生):线程被实例化,但是还没有开始执行
    Runnable(就绪):没有争抢到时间片
    Running(运行):争抢到了时间片,开始执行线程中的任务
    Blocked(阻塞):线程再执行的过程中遇到突发状况,使得其他的线程争抢去了时间片,被阻塞的线程会等待合适的时机重新进入就绪状态
    Dead(死亡):线程终止
    a.run方法执行完毕,线程正常结束
    b.直接调用该线程的stop方法强制终止这个线程(这种做法比较危险,死锁)

    四、线程的常用方法
    1.设置线程的优先级
    可以通过设置优先级来改变线程抢到时间片的概率,优先级高的线程抢到时间片的概率比较高,可以获得更多的执行机会

    默认情况下,每个线程的优先级都与创建它的的父线程具有相同的优先级
    setPriority(),所传的参数范围1~10,默认为5,对应的数值越大,说明优先级越高,这个方法的设置一定要在start之前

    2.使得线程休眠
    使得当前正在执行的线程休眠一段时间,释放时间片,导致线程进入阻塞状态
    sleep(5000);5000代表的是毫秒
    设置了sleep就相当于将当前线程挂起5s,这个操作跟线程的优先级无关,当对应的时间到了之后,还会再执行,
    如果只设置了优先级的话,等于给设置了优先级的线程设置冲突,那么被挂起的是优先级比较低的那个线程

    3.中断线程
    interrupt()
    interrupt只是改变一个线程的状态,并不是真正的停止一个线程
    如果线程处于阻塞状态(sleep,join),则中断状态被清除
    如果一个线程没有处于阻塞状态,这时调用interrupt将不起作用,否则,会引起InterruptedException异常(该线程预先准备好处理此状况)

    实际看到的效果:停止了线程

    在线程的执行体中,可以通过 boolean isInterrupted() 来测试线程是否已经中断。


    4.线程合并
    join()
    优先执行被合并进来的线程,执行完合并进来的线程之后,再执行原来的线程


    5.后台线程
    setDeamon()
    又被称为守护线程或者精灵线程
    特征:如果所有的前台线程都死亡,后台线程会自动死亡

    这个方法的调用需要在start之前

    6.线程让步
    yield()
    yield方法是一个和sleep方法相似的方法
    它可以让当前正在执行的线程暂停,但他不会阻塞该线程,它只是将该线程转入就绪状态,完全会出现的一个情况是:当某个线程调用了yield方法暂停之后,线程调度器可能会将该线程立马调起来进入执行状态
    实际上,只有优先级相同或者优先级更高的线程才有可能获取执行的机会

    yield方法和sleep方法的区别:
    a.sleep方法暂停当前线程之后,会给其他线程执行的机会的,但是跟线程的优先级没有关系,yield只有优先级相同或者优先级更高的线程才有可能获取执行的机会
    b.sleep会将一个线程转入阻塞状态,但是yield不会,只是做出了让步
    c.sleep会有InterruptedException的异常,但是yield没有
    d.sleep可以有更好的可移植性,通常不要依靠yield来控制并发的线程

  • 相关阅读:
    DirectUI的初步分析转
    win32中调用Atl控件
    win32 DirectUI控件开发与调用指南
    sqlite in qt
    Visual Studio2010中使用IE调试Atl
    silveright使用配置文件转
    Windows phone app 商店认证注意事项简要认证规范指南
    Silverlight桌面部署器及其使用
    Lua语言如何调用自己编写的C DLL 转
    使用Visual Leak Detector for Visual C++ 捕捉内存泄露
  • 原文地址:https://www.cnblogs.com/lidar/p/7743279.html
Copyright © 2011-2022 走看看