美文网首页
JJJJJava线程

JJJJJava线程

作者: 南在南方i | 来源:发表于2019-08-19 10:56 被阅读0次

    进程 :正在运行的一个程序

    • 系统会为这个进程分配独立的内存资源

    线程 :集体执行任务的最小单位

    • 一个进程最少拥有一个线程(主线程 运行起来就执行的线程)
    • 线程之间是共享内存资源的(进程申请的)
    • 线程之间可以通信(数据传递:多数为主线程和子线程之间传递)
    • 每一个线程都有自己的运行回路(生命周期)

    线程的生命周期

    image.png

    1.新建状态

    • 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runnable)
    • 注意:不能对已经启动的线程再次调用start()方法,否则会出现Java.lang.IllegalThreadStateException异常

    2.就绪状态

    • 处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列(尽管是采用队列形式,事实上,把它称为可运行池而不是可运行队列。因为cpu的调度不一定是按照先进先出的顺序来调度的),等待系统为其分配CPU。等待状态并不是执行状态,当系统选定一个等待执行的Thread对象后,它就会从等待执行状态进入执行状态,系统挑选的动作称之为“cpu调度”。一旦获得CPU,线程就进入运行状态并自动调用自己的run方法
    • 提示:如果希望子线程调用start()方法后立即执行,可以使用Thread.sleep()方式使主线程睡眠一伙儿,转去执行子线程

    3.运行状态

    • 处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态
      处于就绪状态的线程,如果获得了cpu的调度,就会从就绪状态变为运行状态,执行run()方法中的任务。如果该线程失去了cpu资源,就会又从运行状态变为就绪状态。重新等待系统分配资源。也可以对在运行状态的线程调用yield()方法,它就会让出cpu资源,再次变为就绪状态
    • 注: 当发生如下情况是,线程会从运行状态变为阻塞状态:
      ①线程调用sleep方法主动放弃所占用的系统资源
      ②线程调用一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
      ③线程试图获得一个同步监视器,但更改同步监视器正被其他线程所持有
      ④线程在等待某个通知(notify)
      ⑤程序调用了线程的suspend方法将线程挂起。不过该方法容易导致死锁,所以程序应该尽量避免使用该方法
      当线程的run()方法执行完,或者被强制性地终止,例如出现异常,或者调用了stop()、desyory()方法等等,就会从运行状态转变为死亡状态

    4.阻塞状态

    • 处于运行状态的线程在某些情况下,如执行了sleep(睡眠)方法,或等待I/O设备等资源,将让出CPU并暂时停止自己的运行,进入阻塞状态
    • 在阻塞状态的线程不能进入就绪队列。只有当引起阻塞的原因消除时,如睡眠时间已到,或等待的I/O设备空闲下来,线程便转入就绪状态,重新到就绪队列中排队等待,被系统选中后从原来停止的位置开始继续运行

    5.死亡状态

    • 当线程的run()方法执行完,或者被强制性地终止,就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。 如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常

    NEW:新建 线程刚被创建好
    RUNNABLE:就绪状态(可运行状态)只要抢到时间片就可以运行这个线程
    BLOCKED:阻塞状态 sleep
    WAITING:等待状态 wait
    TIMED_WAITING:一个正在限时等待另一个线程执行一个动作的线程处于这一状态
    TERMINATED:终止


    为什么需要创建子线程

    • 如果在主线程中存在有比较耗时的操作:下载视频 上传文件 数据传输
    • 这些操作会阻塞主线程 后面的任务必须等这些任务执行完毕之后才能执行 用户体验比较差
    • 为了不阻塞主线程 需要将耗时的任务放在子线程中去处理

    如何创建一个子线程

    1.写一个类继承于Thread 实现run方法

    • join:让当前这个线程阻塞 等join的线程执行完毕再执行
    • setName:设置线程名称
    • getName:获取线程名称
    • currentThread:获取当前运行的线程对象
    • start:开启任务
    class Ticker extends Thread{
        private int i;
    
        @Override
        public void run() {
            for(i=1;i<=100;i++) {
                //返回当前线程的名字
                System.out.println(getName()+":"+i);
            }
        }
    
        public static void main(String[] args){
            //main方法里面执行的代码 是在主线程里面执行的
            //(geiName)     主线程的名称是main
            String name =  Thread.currentThread().getName();
            System.out.println(name);
    
            //创建Thread的对象
            Ticker tt1 = new Ticker();
    
            //设置线程的名称
            tt1.setName("子线程1");
    
            //开启任务
            tt1.start();
        }
    }
    

    2.实现Runnable接口 实现run方法

    • a.创建任务 创建类实现Runnable接口
    • b.使用Thread 为这个任务分配线程
      方法2.png
      3.目前不建议使用Lambda表达式 阅读性太差

    相关文章

      网友评论

          本文标题:JJJJJava线程

          本文链接:https://www.haomeiwen.com/subject/xizjsctx.html