zoukankan      html  css  js  c++  java
  • java基础知识回顾之java Thread类学习(四)线程的状态以及转化使用的方法介绍

    java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍

     

       线程的概述:

            线程是程序的多个执行路径,执行调度的单位,依托于进程存在。线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系统分配的,主要用来保存线程内部的数据,如线程执行函数中定义的变量。

        java中多线程是一种抢占机制而不是分时机制。抢占机制是指CPU资源师被多个线程所共享,多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU.可以参考java 进程与线程的区别

     线程的状态:

    • 新生状态(New):当一个线程被创建一个线程实例后new Thread()或者new Thread(Runnable r),此线程处于新生状态,处于新生状态,线程有自己的内存空间,但该线程没有运行,此时该线程还不是活着的(not Alive)。
    • 就绪状态(Runnable):通过线程对象的start()方法启动线程使线程进入就绪状态(runnable),处于就绪状态的线程具备了运行条件(CPU执行资格),但是还没有抢到CPU执行权,不一定会被立即执行。此时线程在线程就绪队列中,等待系统为其分配CPU.等待状态不是执行状态,此时线程是活着的(isAlive=true).
    • 运行状态(Running):一旦线程抢到CPU执行权,线程进入运行状态(running),线程run方法才开始执行,运行状态的线程执行自己run方法里面的代码,直到调用其他方法而终止,或者等待某种资源而阻塞,或者完成任务而死亡;如果再给定的时间片内程序没有执行结束,就会被系统暂停当前正在运行的调度程序,回到线程的等待状态。此时线程是活着的(Alive)
    • 阻塞状态:(Blocked):通过调用join,sleep,wait或者资源被占用,使线程处于阻塞状态(blocked),处于阻塞状态的线程仍然活着。
    • 死亡状态:(Dead):当一个线程的run方法中的代码运行完毕,或被中断,或被异常退出,该线程处于死亡状态。一旦线程进入dead状态,它就再也不能进入一个独立线程的生命周期了,对一个处于dead状态的线程调用start方法,会出现runtime exception异常;处于dead状态的线程不是活着的(Alive)

     线程的方法和属性:

    • 优先级(priority):每一个线程都有一个优先级。默认优先级是5,优先级最高是10;优先级高的线程并不一定比优先级低的线程执行的机会高,只是执行的机率高;默认一个线程的优先级和创建他的线程优先级相同;setPriority(Thread.MAX_PRIORITY)方法来设置线程的优先级。
    • sleep(long millis)/sleep(long millis, int nanos)线程休眠:使当执行的线程休眠指定时间。作用:保持对象锁,让出CPU,调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留一定的时间给其他线程执行的机会;
    • Thread.yield():让出CPU的执行权,暂停当前执行的线程对象,让同等优先级的线程运行。稍微的释放执行权一会儿,时间不会很长。
    • Thread.join():用来临时加入线程执行,抢夺CPU执行权。例如:当A线程执行到B线程的Join方法时,A就会等待,等B线程执行完之后,A线程才会执行。
    •   object.wait():用在同步中,如果不在锁中使用会抛出IllegalMonitorStateException异常。使线程处于阻塞状态,是线程进入等待池中,释放锁,释放执行权

    • object.notify()/notifyAll():唤醒在当前对象等待池中等待的第一个线程/所有线程。notify()/notifyAll()也必须拥有相同对象锁,否则也会抛出IllegalMonitorStateException异常。
    •   Synchronizing Block:机锁具有独占性、一旦被一个Thread持有,其他的Thread就不能再拥有(不能访问其他同步方法),方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。

    下面给出上面方法的测试代码:

       yield(),join(),priority属性的测试,其它方法不测试了,在是我的文章里面可以看到:

     设计两个线程,一个线程为主线程,一个线程Thread-0:

    代码:没有用Join方法主线程和Thread-0交替的执行。大家都知道,这里不测试了。但是用了join方法大家看效果.

    join方法的源码:      

    复制代码
    * Waits at most {@code millis} milliseconds for this thread to
    * die. A timeout of {@code 0} means to wait forever. * * <p> This implementation uses a loop of {@code this.wait} calls * conditioned on {@code this.isAlive}. As a thread terminates the * {@code this.notifyAll} method is invoked. It is recommended that * applications not use {@code wait}, {@code notify}, or * {@code notifyAll} on {@code Thread} instances. * * @param millis * the time to wait in milliseconds * * @throws IllegalArgumentException * if the value of {@code millis} is negative * * @throws InterruptedException * if any thread has interrupted the current thread. The * <i>interrupted status</i> of the current thread is * cleared when this exception is thrown.
    */
    // 加锁当前线程
    public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) {
    //A线程是start,在运行中 while (isAlive()) {
              //main线程等待 wait(0); } } else {
    //join(timeOut)的情况 while (isAlive()) {
              //根据当前timeout的时间-now 是否<=0进行判断,主线程是否继续阻塞等待 long delay = millis - now;
    //等待超时时间到了,则主线程不阻塞了,等待结束 if (delay <= 0) { break; } wait(delay);
    //子线程从循环开始到现在运行的时间 now = System.currentTimeMillis() - base; } } }
    复制代码

    给一个例子来理解:

    复制代码
    package concurrentMy.joins;
    
    /**
     * 
     * @author Administrator
     * 
     * main 线程 和 A线程,A线程是main线程创建并且启动的,main线程优先级比较高,正在执行;
     * 这个时候main线程调用A.join()之后,main线程一直等待,直到A线程运行完毕,main线程才运行
     * 
     */
    class ThreadA extends Thread {
        
        public ThreadA(String name){
            super(name);
        }
    
        @Override
        public void run() {
           、
            for (int i = 0; i < 20; i++) {
                // 复写父类的toString方法, 返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
                // Thread[Thread-1,5,main]默认的优先级为5,优先级从1-10
                System.out.println(Thread.currentThread().getName() + "-" + i);
    
            }
        }
    
    }
    
    public class JoinDemo {
    
        /**
         * @param args
         * @throws InterruptedException 
         */
        public static void main(String[] args) throws InterruptedException {
            ThreadA A = new ThreadA("线程A");
            A.start();
            A.join(); //A线程加入到“main线程”中,main线程一直等待,直到A线程执行完毕,main线程才运行
            System.out.println(Thread.currentThread().getName() + "执行");
            System.out.println(Thread.currentThread().getName() + "执行终止");
    
        }
    
    }
    复制代码

     输出结果:

    复制代码
    线程A-0
    线程A-1
    线程A-2
    线程A-3
    线程A-4
    线程A-5
    线程A-6
    线程A-7
    线程A-8
    线程A-9
    线程A-10
    线程A-11
    线程A-12
    线程A-13
    线程A-14
    线程A-15
    线程A-16
    线程A-17
    线程A-18
    线程A-19
    main执行
    main执行终止
      
    复制代码

    代码运行整个过程如下图:

     

     

     

    例子2,优先级测试

    复制代码
    package com.lp.ecjtu.Thread;
    /**
     * 
     * @author Administrator
     * 当A线程执行到B线程的Join方法时,A就会等待,等B线程执行完之后,A线程才会执行
     * Join方法可以用来临时加入线程执行
     */
    class Join implements Runnable{
    
        @Override
        public void run() {
            for(int i=0;i<20;i++){
                //复写父类的toString方法, 返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
                //Thread[Thread-1,5,main]默认的优先级为5,优先级从1-10
                System.out.println(Thread.currentThread().toString()+"-"+i);
                
            }
        }
        
    }
    public class JoinDemo {
    
        /**
         * @param args
         * @throws InterruptedException 
         */
        public static void main(String[] args) throws InterruptedException {
            Join join = new Join();
            Thread t1 = new Thread(join);
            Thread t2 = new Thread(join);
            t2.setPriority(Thread.MAX_PRIORITY);//设置线程的优先级的方法
            t1.start();
            t2.start();
           
        }
    
    }
    复制代码

    输出结果:

    Thread[Thread-1,10,main]-0
    Thread[Thread-1,10,main]-1
    Thread[Thread-1,10,main]-2
    Thread[Thread-1,10,main]-3
    Thread[Thread-1,10,main]-4
    Thread[Thread-1,10,main]-5
    Thread[Thread-1,10,main]-6
    Thread[Thread-0,5,main]-0
    Thread[Thread-1,10,main]-7
    Thread[Thread-1,10,main]-8
    Thread[Thread-0,5,main]-1
    Thread[Thread-1,10,main]-9
    Thread[Thread-1,10,main]-10
    Thread[Thread-1,10,main]-11
    Thread[Thread-1,10,main]-12
    Thread[Thread-1,10,main]-13
    Thread[Thread-1,10,main]-14
    Thread[Thread-1,10,main]-15
    Thread[Thread-1,10,main]-16
    Thread[Thread-1,10,main]-17
    Thread[Thread-1,10,main]-18
    Thread[Thread-0,5,main]-2
    Thread[Thread-1,10,main]-19
    Thread[Thread-0,5,main]-3
    Thread[Thread-0,5,main]-4
    Thread[Thread-0,5,main]-5
    Thread[Thread-0,5,main]-6
    Thread[Thread-0,5,main]-7
    Thread[Thread-0,5,main]-8
    Thread[Thread-0,5,main]-9
    Thread[Thread-0,5,main]-10
    Thread[Thread-0,5,main]-11
    Thread[Thread-0,5,main]-12
    Thread[Thread-0,5,main]-13
    Thread[Thread-0,5,main]-14
    Thread[Thread-0,5,main]-15
    Thread[Thread-0,5,main]-16
    Thread[Thread-0,5,main]-17
    Thread[Thread-0,5,main]-18
    Thread[Thread-0,5,main]-19

    总结:从结果可以看出Thread-1,10,main优先级为10的线程2先执行。

    yield方法是正在执行的线程释放执行权,暂停执行一小会儿。这里不测了。。。。。。

  • 相关阅读:
    Tomcat性能调优
    spring 提供的可扩展的接口和类
    Spring boot 定义exit codes 让你定位问题更加简单
    spring中@Async注解的原理和使用
    SpringCache源码深度解析
    ApplicationContextAware和BeanFactoryAware使用理解
    spring aop中引介拦截器的用法
    提高安全性而在HTTP响应头中可以使用的各种响应头字段
    spring aop中targetSource的理解
    PowerMockito使用PowerMockIgnore注解消除类加载器引入的ClassCastException
  • 原文地址:https://www.cnblogs.com/hanease/p/15721281.html
Copyright © 2011-2022 走看看