• 多线程JAVA篇(一)


    解析AsyncTask源码之前,首先讲述与之相关的Java线程知识:

    知识点清单
    1、Thread类
    2、Runnable接口
    3、Callable接口
    4、synchronized关键字
    5、volatile关键字
    6、Future接口
    7、RunnableFuture接口
    8、FutureTask类
    9、线程池的相关知识

    /**
         * A representation of a thread's state. A given thread may only be in one
         * state at a time.
         */
        public enum State {
            /**
             * The thread has been created, but has never been started.
             */
            NEW,
            /**
             * The thread may be run.
             */
            RUNNABLE,
            /**
             * The thread is blocked and waiting for a lock.
             */
            BLOCKED,
            /**
             * The thread is waiting.
             */
            WAITING,
            /**
             * The thread is waiting for a specified amount of time.
             */
            TIMED_WAITING,
            /**
             * The thread has been terminated.
             */
            TERMINATED
        }
    

    大家发现这个枚举里面列举了六种状态,实际上线程一共只有四种状态:
    1、新建(NEW):当线程被创建时,它只会短暂处于这种状态。此时它已经分配了必需的系统资源,并执行了初始化。此刻线程已经有了资格获得CPY时间,之后调度器将把这个线程转变为可运行状态或阻塞状态。
    2、就绪(RUNNABLE):在这种状态下,只要调度器把时间片分配给线程,线程就可以运行。也就是说,在任意时刻,线程可以运行也可以不运行。只要调度器能分配时间片给线程,它就可以运行;这不同于死亡和阻塞状态。
    3、阻塞(BLOCKED、WAITING、TIMED_WAITING):线程能够运行,但有某个条件阻止它的运行。当线程处于阻塞状态时,调度 器将会忽略线程,不会分配给线程任何CPU时间。直到线程重新进入就绪状态,它才有可能执行操作
    4、死亡(TERMINATED)处于死亡或终止状态的线程将不再是可调度的,并且再也不会得到CPU时间,它的任务已结束,或不再是可运行的。任务死亡的通常方式从run方法返回,但是任务的线程还可以被中断,你将要看到这一点。
    下面通过代码实例的方法为大家演示这六种状态:

    public class ThreadTest {
    
        public static void main(String[] args) {
            final Thread thread = new Thread(new Runnable() {
    
                @Override
                public void run() {
                    for (int i = 0; i < 10000; i++) {
    
                    }
    
                }
            });
    
            System.out.println("线程名" + thread.getName() + "线程状态" +thread.getState());
    
            thread.start();
    
            System.out.println("线程名" + thread.getName() + "线程状态" +thread.getState());
    
            Thread threadTest = new Thread(new Runnable() {
    
                @Override
                public void run() {
                    System.out.println("线程名" + thread.getName() + "线程状态" +thread.getState());
                }
            });
    
            System.out.println("线程名" + threadTest.getName() + "线程状态" +threadTest.getState());
    
            threadTest.start();
    
            System.out.println("线程名" + thread.getName() + "线程状态" +thread.getState());
            System.out.println("线程名" + threadTest.getName() + "线程状态" +threadTest.getState());
        }
    }
    

    打印日志1:

    线程名Thread-0线程状态NEW
    线程名Thread-0线程状态RUNNABLE
    线程名Thread-1线程状态NEW
    线程名Thread-0线程状态TERMINATED
    线程名Thread-1线程状态RUNNABLE
    线程名Thread-0线程状态TERMINATED

    打印日志2:

    线程名Thread-0线程状态NEW
    线程名Thread-0线程状态RUNNABLE
    线程名Thread-1线程状态NEW
    线程名Thread-0线程状态RUNNABLE
    线程名Thread-1线程状态RUNNABLE
    线程名Thread-0线程状态RUNNABLE

    public class ThreadTestTwo {
    
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
    
                @Override
                public void run() {
                    for (int i = 0; i < 1000000000; i++) {
    
                    }
    
                }
            });
    
            System.out.println("线程名" + thread.getName() + "线程状态"
                    + thread.getState());
    
            thread.start();
    
            System.out.println("线程名" + thread.getName() + "线程状态"
                    + thread.getState());
    
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            System.out.println("线程名" + thread.getName() + "线程状态"
                    + thread.getState());
        }
    }
    
     

    打印日志:

    线程名Thread-0线程状态NEW
    线程名Thread-0线程状态RUNNABLE
    线程名Thread-0线程状态RUNNABLE

    我来为大家分析一下这几个日志:
    大家可以看到第一个线程就是thread线程,在Thread.start()方法调用之前是这个线程的状态是New(新建状态),在线程 Thread.start()方法调用之后线程的状态为Runnbale(就绪状态),在任务执行完之后状态变为Terimal(终止状态),大家可能发 现打印日志1和打印日志2略有不同,因为当线程threadTest的启动了之后,thread的任务有没有执行完成其实是一个未知不可确定的事情。这个 测试代码中还有一个知识点,大家有没有发现最后日志打印结果显示打印的最后日志竟然是Thread-0,很多人要问了最后一个日志不应该是 threadTest(Thread-1)么,其实不是因为threadTest的这个是在主线程中执行的,而有一个打印是在threadTest方法中 的,所以threadTest.run()方法中的打印日志才是最后一个,主线程的优先级是要比普通线程的优先级要高。但是不要去使用优先级去控制线程的 执行顺序,因为那并不可靠。但是因为优先级这部分使用的很少,也不是很重要,这里就不详细论述了,有兴趣的可以去看看。
    通过上面这部分测试代码我们认识了线程这个类的三种状态,总结一下:
    1、一个线程创建之后没有调用Thread.start()方法之前线程的状态是NEW
    2、一个线程调用Thread.start()方法之后,线程的状态是RUNNABLE,无论线程是否在运行状态下线程,大家可以看第二个日志调用了Thread.sleep()方法线程的状态并没有改变可以得知
    3、一个线程执行完任务之后,线程的状态就是Terimal(终结)

    下面为大家讲述线程中的另外一个状态阻塞,阻塞状态又分三种(BLOCKED、WAITING、TIMED_WAITING),在讲阻塞状态之前又不可避免的先要为大家讲述一下synchronized这个关键字

  • 相关阅读:
    算法与数据结构——排序(五)希尔排序
    算法与数据结构——排序(四)简单插入排序
    算法与数据结构——排序(九)快速排序
    算法与数据结构——排序(六)堆排序
    [Keil51]51单片机定时器的方式0使用注意
    [转]简单的随机数加密算法实现
    [KeilC51]MCS51指令集中ret和reti的区别___待续
    [C]FILE结构体(不知其然,不知所以然)
    [KeilC51]这几天遇到的问题
    [KeilC51] keil c51编译器不支持匿名结构体
  • 原文地址:https://www.cnblogs.com/ljsy-yjx/p/5472741.html
Copyright © 2020-2023  润新知