Java提升——多线程(一)状态图

操做系统中的进程和线程的概念
       进程是指一个内存运行的应用程序,每一个进程都有本身独立的一块内存空间,一个进程中能够启动多个线程,好比windows下的一个运行的应用程序.exe就是一个进程。
       线程是指进程中的一个执行流,一个进程能够运行多个线程。如java.exe就能够运行不少个线程。线程老是属于某个进程,进程中的多个线程共享进程中的内存。
       操做系统中能够同时执行多个任务,每一个任务就是进程;进程能够同时执行多个任务,每一个任务就是线程。
   
线程的状态


一、新建(new):线程对象被建立后就进入了新建状态。如:Thread thread = new Thread();java

二、就绪状态(Runnable):也被称为“可执行状态”。线程对象被建立后,其余线程调用了该对象的start()方法,从而启动该线程。如:thread.start(); 处于就绪状态的线程随时可能被CPU调度执行。windows

三、运行状态(Running):线程获取CPU权限进行执行。须要注意的是,线程只能从就绪状态进入到运行状态。多线程

四、阻塞状态(Blocked):阻塞状态是线程由于某种缘由放弃CPU使用权限,暂时中止运行。直到线程进入就绪状态,才有机会进入运行状态。阻塞的三种状况:ide

    1)等待阻塞:经过调用线程的wait()方法,让线程等待某工做的完成。this

    2)同步阻塞:线程在获取synchronized同步锁失败(由于锁被其余线程占用),它会进入同步阻塞状态。spa

    3)其余阻塞:经过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或超时、或者I/O处理完毕时,线程从新转入就绪状态。
操作系统

五、死亡状态(Dead):线程执行完了或因异常退出了run()方法,该线程结束生命周期。线程

经常使用的实现多线程的方式

一、继承Thread类3d

public class Thread implements Runnable {、、、、、}

由Thread的源码能够看出,Thread是实现了Runnable接口。code

二、实现Runnable接口

public interface Runnable {
     public abstract void run(); }

Runnable接口只有一个run()方法

————————————————————————————————————————————————

Thread和Runnable都是是实现实现多线程的方式。不一样的是Thread是类,Runnable是接口——Thread自己实现了Runnable接口,一个类只能有一个父类,可是却能够是实现多个接口,所以Runnable具备更好的扩展性

Thread实现多线程

public class MyThread extends Thread {
    private int i ;  @Override/** 重写run方法*/  public void run(){
        for (int i = 0; i < 50 ; i++) {
            /**  * 当继承Thread类能够直接用this获取当前线程  * 用getName()获取当前线程的名字  */  System.out.println(this.getName()+"-"+i);  }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100 ; i++) {
            //经过Thread.currentThread()获取当前线程  System.out.println(Thread.currentThread().getName()+" "+i);  if(i==20){
                //建立并启动第一个线程  new MyThread().start();  //建立并启动第二个线程  new MyThread().start();  }
        }
    }
}

Runnable实现多线程

public class MyRunnable implements Runnable {
    private int i;   @Override  public void run() {
        for (int i = 0; i < 50; i++) {
            /**当线程类实现Runnable接口的时候,获取当前线程只能用Thread.currentThread()*/  System.out.println(Thread.currentThread().getName()+" "+i);  }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
           // System.out.println(Thread.currentThread().getName()+" "+i);  if(i==20){
                MyRunnable mr = new MyRunnable();  //经过new Start()方法建立新线程  new Thread(mr,"线程1").start();  new Thread(mr,"线程2").start();  }

        }
    }
}
关于线程中的start()和run()

启动线程使用start(),而不是run()!


在执行start()方法以前,只是有一个Thread对象,还没一个真正的线程。(分配内存,初始化成员变量

——>start()以后,线程状态重新状态到可执行状态。(调用栈和计数器,线程没运行,只是能够运行

——>当线程得到执行机会时,其目标run()方法将运行。

start():他的做用是启动一个新线程,新线程会调用相应的run()方法。start()不能被重复调用。

run():和普通成员的方法同样能够被重复调用。单独调用run()会在当前线程中执行run(),而不会启动新的线程。

public class MyThread extends Thread {  @Override/** 重写run方法*/  public void run(){
       
        }
    }
MyThread myThread = new MyThread();

如:myThread.start()会启动一个新的线程,而后在新线程中执行run()方法。

myThread.run()会直接在当前线程中运行run()方法,不会启动一个线程。

start方法源码:

public synchronized void start() {
     /**     *若是线程不是就绪状态就抛出异常     */  if (threadStatus != 0)
         throw new IllegalThreadStateException();   /* 将线程添加到group当中 */  group.add(this);   boolean started = false;  try {
         start0();//经过start0启动线程  started = true;//设置started标记  } finally {
         try {
             if (!started) {
                 group.threadStartFailed(this);  }
         } catch (Throwable ignore) {
             /* do nothing. If start0 threw a Throwable then  it will be passed up the call stack */  }
     }
 }

run方法源码:

public void run() {
    if (target != null) {
        target.run();  }
}

其中target是Runnable对象, 直接调用Thread线程中Runnable接口中run方法,不会新建一个线程。

当线程得到CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。

关于阻塞


进入阻塞的状况:   解除上面阻塞状况:

一、线程调用sleep()方法主动释放占用的处理器资源

二、调用了一个阻塞式的IO方法,在方法返回前线程被阻塞

三、线程得到了一个同步监视器(Syschronized),但该监视器正被其余线程持有

四、线程在等待某个通知(notify)

五、程序调用了线程的resume()方法将线程挂起。可是该方法容易发生死锁,因此尽可能避免使用

 

一、调用sleep()方法通过了指定的时间

二、线程调用的IO阻塞方法已经返回

三、线程成功的得到了试图取得的同步监视器

四、线程正在等待某个通知时,其余线程发出了一个通知

五、处于挂起的线程被调用了resume()恢复方法。

线程从阻塞状态只能进入就绪状态,没法进入运行状态,而从就绪到运行不受程序控制,由系统线程调度决定。

得到资源进入运行状态,失去资源进入就绪状态。

线程死亡


线程死亡会以一下三种情况结束:

—>调用run或call方法执行完成,正常结束

—>线程抛出一个为捕获的Exception或Error

—>直接调用stop()方法来结束该线程——容易致使死锁,不推荐


不要试图对死亡的线程使用start()方法,将会抛出异常,并不会重启死亡的异常!

相关文章
相关标签/搜索