• 线程的创建和运行


    C语言可以访问内存地址,Java里不可以访问内存地址
    JAVA里面只支持单继承

    线程是一个程序内部的顺序控制流
    线程和进程的区别:
    进程是指运行中的应用程序,每一个进程都有自己独立的内存空间。对一个应用程序可以同时启动多个进程。例如每次执行JDK的java.exe程序,就启动了一个独立的Java虚拟机进程,该进程的任务是解析并执行Java程序代码
    线程是指进程中的一个执行流程,有时也称为执行情景。一个进程可以由多个线程组成,即在一个进程中可以同时运行多个不同的线程,它们分别执行不同的任务。当进程内的多个线程同时运行,这种运行方式称为并发运行。

     程序、进程与多任务
    程序(program)是对数据描述与操作的代码的集合,是应用程序执行的脚本。
    进程(process)是程序的一次执行过程,是系统运行程序的基本单位。程序是静态的,进程是动态的。系统运行一个程序即是一个进程从创建、运行到消亡的过程。
    多任务(multi task)在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每个任务对应一个进程。

    多进程优点:各个进程独立,互不影响
    缺点:各个进程独立造成交流困难,进程交流涉及到进程的通信,比较麻烦

    JAVA里面不支持多进程,只支持多线程。
    多线程优点:多线信息传递快
    减轻编写交互频繁、涉及面多的程序的困难(如监听网络端口)。
    程序的吞吐量会得到改善(同时监听多种设备,如网络端口、串口、并口以及其他外设)。
     有多个处理器的系统,可以并发运行不同的线程(否则,任何时刻只有一个线程在运行)。


    多线程缺点:每个线程公用一块数据,所以有锁的控制,这也是比较麻烦的。

    每个线程都是通过某个特定Thread对象所对应的方法run( )来完成其操作的,方法run( )称为线程体。
    使用start()方法,线程进入Runnable(可运行)状态,它将向线程调度器注册这个线程。
    调用start()方法并不一定马上会执行这个线程,正如上面所说,它只是进入Runnable 而不是Running。
    注意,不要直接在程序中调用线程的run()方法。

    为了规范,一定要给自己创建的线程命名!!!
    JAVA里面多线程的创建有下面两种方法:
    (Java语言在设计之初就加入了对线程的支持,开发人员可以使用JDK提供的相关API创建基于多线程的应用程序
    每个Java程序启动后,虚拟机将自动创建一个主线程,也可以通过以下两种方式自定义线程类:
    创建java.lang.Thread类的子类,重写该类的run方法
    创建java.lang.Runnable接口的实现类,实现接口中的run方法

    通过java.lang.Thread来创建一个线程


    Thread类-2
    Thread类中的重要方法:
    run方法:包括线程运行时执行的代码,通常在子类中重写它。
    start方法:启动一个新的线程,然后虚拟机调用新线程的run方法


    采用implements Runnable方法创建线程
    由于继承了Thread后,类再不能继承别的类,所以一般我们采用实现Runnable接口的方法来创建线程。
    提供一个实现接口Runnable的类,实现run()方法。
    得到这个类的实例A。
    New 这个一个Thread对象,同时A作为参数传入。
      例如:Thread runner=new Thread(A);
    调用start启动线程
           例如:runner.start();


    Runnable接口
    java.lang.Runnable接口中只有一个未实现的run方法,实现该接口的类必须重写该方法。
    Runnable接口与Thread类之间的区别
    Runnable接口必须实现run方法,而Thread类中的run方法是一个空方法,可以不重写
    Runnable接口的实现类并不是真正的线程类,只是线程运行的目标类。要想以线程的方式执行run方法,必须依靠Thread类。

    启动线程:
       每个线程都是通过某个特定Thread对象所对应的方法run( )来完成其操作的,方法run( )称为线程体。
    使用start()方法,线程进入Runnable(可运行)状态,它将向线程调度器注册这个线程。
    调用start()方法并不一定马上会执行这个线程,正如上面所说,它只是进入Runnable 而不是Running。
    注意,不要直接在程序中调用线程的run()方法。


    线程的生命周期
    指线程从创建到启动,直至运行结束这段时间
    可以通过调用Thread类的相关方法影响线程的运行状态

    线程的运行状态:
    新建(New)
    可执行(Runnable)
    运行(Running)
    阻塞(Blocking)
    死亡(Dead)

    新建状态(New)
    当创建了一个Thread对象时,该对象就处于“新建状态”
    没有启动,因此无法运行
    可执行状态(Runnable)
    其他线程调用了处于新建状态线程的start方法,该线程对象将转换到“可执行状态”
    线程拥有获得CPU控制权的机会,处在等待调度阶段。
    运行状态(Running)
    处在“可执行状态”的线程对象一旦获得了CPU控制权,就会转换到“执行状态”
    在“执行状态”下,线程状态占用CPU时间片段,执行run方法中的代码
    处在“执行状态”下的线程可以调用yield方法,该方法用于主动出让CPU控制权。线程对象出让控制权后回到“可执行状态”,重新等待调度。
    阻塞状态(Blocking)
    线程在“执行状态”下由于受某种条件的影响会被迫出让CPU控制权,进入“阻塞状态”。
    进入阻塞状态的三种情况:
    调用sleep方法(调用sleep方法
    public void sleep(long millis)
    Thread类的sleep方法用于让当前线程暂时休眠一段时间
    参数millis的单位是毫秒

    调用join方法(将多线程又变成单线程)(调用join方法(合并某个线程)
    处在“执行状态”的线程如果调用了其他线程的join方法,将被挂起进入“阻塞状态”
    目标线程执行完毕后才会解除阻塞,回到“可执行状态”
    执行I/O操作
    线程在执行过程中如果因为访问外部资源(等待用户键盘输入、访问网络)时发生了阻塞,也会导致当前线程进入“阻塞状态”。

    执行I/O操作

    解除阻塞
    睡眠状态超时
    调用join后等待其他线程执行完毕
    I/O操作执行完毕
    调用阻塞线程的interrupt方法(一般不调用这个方法)


    死亡状态(Dead)
    处于“执行状态”的线程一旦从run方法返回(无论是正常退出还是抛出异常),就会进入“死亡状态”。
    已经“死亡”的线程不能重新运行,否则会抛出IllegalThreadStateException
    可以使用Thread类的isAlive方法判断线程是否活着

     
    线程调度
    按照特定机制为线程分配CPU时间片段的行为
    Java程序运行时,由Java虚拟机负责线程的调度
    线程调度的实现方式
    分时调度模型(CPU默认的方法):让所有线程轮流获得CPU的控制权,并且为每个线程平均分配CPU时间片段
    抢占式调度模型:选择优先级相对较高的线程执行,如果所有线程的优先级相同,则随机选择一个线程执行。Java虚拟机采用此种调度模型。

    “synchronized”关键字:
    为了防止共享对象在并发访问时出现错误,Java中提供了“synchronized”关键字。
    synchronized关键字
    确保共享对象在同一时刻只能被一个线程访问,这种处理机制称为“线程同步”或“线程互斥”。Java中的“线程同步”基于“对象锁”的概念

    当一个线程访问对象的同步方法时,被访问对象就处于“锁定”状态,访问该方法的其他线程只能等待
    可以加在方法前,还可以加在代码块里面。

  • 相关阅读:
    Debian9 挂载本地ISO当镜像源
    debian9使用ls命令显示文件和文件夹颜色
    debian无法使用netstat
    debian9修改MariaDB用户密码和配置
    python2安装mysqlclient报错EnvironmentError: mysql_config not found
    debian9部署python2虚拟环境
    Debian9安装MariaDB
    Debian9配置网络源
    向日葵远程按键失灵
    Debian9修改时区
  • 原文地址:https://www.cnblogs.com/kelan/p/5284504.html
Copyright © 2020-2023  润新知