• 1.线程生命周期


    线程的生命周期:一个线程从创建到消亡的过程

    如下图,表示线程生命周期中的各个状态:

    线程的生命周期可以分为五个状态:

    1.创建状态:

      当用new操作符创建一个新的线程对象时,该线程处于创建状态。

      处于创建状态的线程只是一个空的线程对象,系统不为它分配资源。

    2.可运行状态【runnable】:

      执行线程的start()方法将为线程分配必须的系统资源,安排其运行,并调用线程体——run()方法,

      这样就使得该线程处于可运行状态(Runnable)。

      这一状态并不是运行中状态(Running),因为线程也许实际上并未真正运行。

           注意:一个线程只有在start()之后才是具备可执行能力的(runnable状态的),但是具备可执行能力

         并不代表着会立即执行(running)一个线程,线程会等待着cpu的调度,只有在cpu调度了该

                      线程之后,该线程才会执行!换句话说:runnable状态的线程可能会立即执行,也可能不会

                      立即执行,只有当runnable状态的线程获得cpu调度执行权的时候才会立即执行!

    3.正在执行状态【running】:

      需要注意的是:线程是被cpu调度的,多个线程或者多个进程之间的切换是由cpu来完成的!

    4.阻塞状态:

      当发生下列事件时,处于运行状态的线程会转入到不可运行状态【阻塞状态】:

      调用了sleep()方法;

      线程调用wait()方法等待特定条件的满足;

      线程输入/输出阻塞。

      或者线程在抢锁的时候

      执行了yield()方法

      返回可运行状态:

      处于睡眠状态的线程在指定的时间过去后;

      如果线程在等待某一条件,另一个对象必须通过notify()或notifyAll()方法通知等待线程条件的改变;

      如果线程是因为输入输出阻塞,等待输入输出完成。

    注意:1.当我们调用Thread.sleep()方法、wait()方法、yield()方法,也或者是争抢锁资源的时候 线程就会由running状态转到blocked【阻

        塞状态】,而一个线程进入阻塞【blocked】, 状态之后,是不能直接恢复到running状态的,它是需要先进入!

               2.另外running状态的线程除了可以通过blocked状态进入runnnable状态的情况外,处于running状态的线程还可以直接进入到runnable

        状态,这是因为cpu调度将执行权交给了其它线程了,多个线程或者多个进程之间的切换是由cpu来完成的!只不过速度很快,你看

        不出来而已,但是在某一个具体的时间点cpu只能执行一个线程!

    5.消亡状态:

      当线程的run()方法执行结束后,该线程自然消亡。

       注意:最后一个状态是终结状态[disabled或者terminated]:当线程正常执行完毕或者也可能是从blocked状态的线程被打断的时候【比如

          sleep()、wait()、抢锁的时候被打断了】就会进入这种终结状态,也有可能由于操作系统的原因,线程会直接从runnable状态进入

          到terminated状态!

    public class MultiThread {
    	public static void main(String[] args) {
    		new Thread("READ-THREAD"){
    			@Override
    			public void run() {
    				System.out.println(Thread.currentThread().getName());
    				readFromDataBase();
    			}
    		}.start();
    		new Thread("WRITE-THREAD"){
    			@Override
    			public void run() {
    				writeDataToFile();
    			}
    		}.start();
    	}
    	
    	private static void readFromDataBase() {
    		//read data from database and handle it
    		try {
    			println("begin read data from db.");
    			Thread.sleep(1000*30L);
    			println("read data done and handle it now");
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		println("the data handle finish and successfully.");
    	}
    	
    	private static void writeDataToFile(){
    		//write data to file
    		try {
    			println("begin write data to file.");
    			Thread.sleep(1000*30L);
    			println("write data done and start handle it now");
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		println("the data handle finish and successfully.");
    	}
    	private static void println(String message){
    		System.out.println(message);
    	}
    	
    }
    

     针对上面的代码,这里需要注意的是我们直接用匿名类对象直接调用的是start()方法,然后JVM虚拟机就会帮我们调用线程的run()方法,所以才会在

    System.out.println(Thread.currentThread().getName());这段代码这里输出了READ-THREAD !如果我们不是用匿名对象,而是创建一个普通的对象,然后用
    普通对象直接调用run()方法,也就如下:
    		Thread t = new Thread("READ-THREAD"){
    			@Override
    			public void run() {
    				System.out.println(Thread.currentThread().getName());
    				readFromDataBase();
    			}
    		};
    		//t.start()
    		t.run();
    

     显然这是不可以的,因为如果我们直接用线程对象调用run()方法,而不是调用start()方法,那么此时该线程就相当于没启动,此时

        System.out.println(Thread.currentThread().getName());输出的将不再是READ-THREAD,而是main线程了!切记切记!

    另外,我们这里也总结一下其它的:

    1.我们知道,进程中包括线程,线程才是真正干事的,也就是说一个进程中至少有一个线程(main线程或者主线程),这个线程是被JVM调用的,而且线程的名字就是main!

    2.实现一个线程,必须创建Thread实例,覆写里面的run方法,并且调用start()方法!这里需要注意:如果我们不调用run方法,那么这个类就是一个普通的实例类,不是多线程!

    3.当调用了一个线程的start()方法之后,此时至少存在两个线程,一个是调用线程的main线程【也就是调用线程的线程】,再一个是这个线程!

    4.线程的生命周期分为:new ,runnable,running,block,terminate等几部分!

  • 相关阅读:
    ASP.NET中的状态保持(转载)
    Win7系统下VS2008安装SP1补丁解决JQuery无智能提示的问题
    合并多个List<T>类型并通过LINQ按指定属性排序
    ASP.NET状态保持:ViewState
    第一部分 CLR基础:第1章 CLR的执行模型
    Oracle存储过程知识汇总
    ASP.NET中Button控件的CommandName和CommandArgument属性用法
    PL/SQL Developer使用
    ASP.NET常用代码汇总
    PL/SQL Developer中文注释乱码的解决办法
  • 原文地址:https://www.cnblogs.com/python-machine/p/7253036.html
Copyright © 2020-2023  润新知