jdk中提供了线程的状态,在Thread类中提供了一个内部的枚举类:State
public enum State { NEW,//新建状态 RUNNABLE,//就绪状态 BLOCKED,//阻塞状态 WAITING,//等待状态 TIMED_WAITING,//睡眠等待状态 TERMINATED;//终止状态 }
用new语句创建的线程处于新建状态,此时和其他对象一样,在堆中仅仅给他分配了内存
当一个线程创建后,调用了start方法,线程状态就进入到就绪状态,处于就绪状态的线程意味着所有需要的资源已经装备就绪,等待CPU的调用,CPU的调度是由操作系统控制的,用户无法操控
处于运行状态的线程占用CPU资源,执行程序代码,只有处于就绪状态的线程才能有机会进入到运行状态
1、如果一个时间片用完或者调用yield方法,线程会从运行状态进入到就绪状态
2、如果线程已经执行结束了,线程会从运行状态进入终止状态
3、如果线程执行过程中因为等待一些资源而进入阻塞状态(WAITING、TIME_WAITTING、BLOCKED)
进入这种阻塞状态的原因可以是:线程期望进入同步方法或者同步代码块(Synchronized),尚未获取到锁资源的情况下,可以从运行状态进入到blocked状态
如果调用wait()方法,就进入到waiting状态,即调用wait()会触发线程从运行状态进入到阻塞状态而无法执行,直到其他线程发出notify或notifyAll这个方法,此时线程才会从waiting状态进入到blocked状态,进而进入就绪状态
如果线程调用sleep(long)、join(long)、wait(long)等方法是,会触发线程进入到TIMED_WAITING状态,即指定了阻塞的时间,到达了给定的时间后就可以继续进入就绪状态等待CPU的调度
当线程退出run()方法时,线程就进入了终止状态,该状态是结束线程的声明周期
一个线程的生命周期中需要的状态:NEW、RUNNABLE、RUNNING、TERMINATED四个状态,当线程需要响应特定资源时,进入到阻塞状态:BLOCKED、WATING、TIMED_WAITING状态
start方法作用是用来启动一个新线程,start方法需要首先调用,start方法是不能被重复调用的
public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { } } } private native void start0();
tart方法的实现是调用了一个native的方法,本质上java创建的多线程其实是有操作系统所提供的多线程方式来创建的
start方法启动子线程是通过调用系统提供的方式来启动线程
run方法中是子线程的执行体
run方法和普通的成员方法一样,可以被重复调用,如果在当前线程调用执行run(),是不会启动新线程
public static native void yield();
yield方法是定义在Thread类下的静态方法
当线程中调用yield方法,会让当前正在执行的线程由”RUNNING“状态进入到”RUNABLE状态“,线程锁占用的锁是不会释放的
yield让出CPU的执行权,当让给谁,是由系统决定的,系统会让具有相同优先级的或更高优先级的线程获取CPU执行权,如果没有相应优先级的线程,当前线程就会立即执行
是让线程休眠,而且是哪个线程调用,就是那个线程休眠
sleep方法是Thread类下的静态方法,该方法执行过程中会抛出InterruptedException异常,即可以终止异常
sleep所在的线程休眠期间,线程会释放掉CPU资源给其他线程,但如果当前线程本身持有锁,锁是不会释放的,
线程会由”RUNNING“状态进入到TIMED_WAITING状态,当到达休眠时间或者是被中断掉休眠,就会从睡眠状态进入到就绪状态,从而等待CPU的调用
方法:
sleep(long millis)
sleep(long millis, int nanos)
这两个方法都是Thread类的静态方法,不属于某个对象
//设置休眠的时间,单位是毫秒 public static native void sleep(long millis) throws InterruptedException; //设置休眠时间 毫秒和纳秒 public static void sleep(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep(millis); }
暂停当前线程,等待子线程的执行,也称之为线程合并,join方法特点将并行执行的事情合并为串行执行。
例如:如果在ta线程中调用tb.join(),则让ta线程停止执行,并让tb线程先执行,直到tb线程执行完毕,ta线程才能继续执行
用来中断当前线程,终止处于阻塞状态的线程
interrupt方法是在Thread类中的一个普通方法,由对象调用该方法
方法:
boolean isInterrupted():判断线程是否发生中断,true:表示中断 false:非中断
interrupt():中断方法
方法特点:
interrupt方法执行是对中断标志位做了修改
1、如果线程当前是可中断的阻塞状态(调用sleep、join、wait等方法会导致线程进入到阻塞状态:WAITING/TIMED_WAITING/BLOCKED),
在任意的其他线程调用t.interrupt方法,那么线程会立即抛出一个InterruptedException异常,退出阻塞状态
2、如果线程t当前存储于运行状态,则调用t.interrupt()方法,线程会继续执行,直到发生了阻塞(调用sleep、join、wait)后立即抛出异常,跳出阻塞状态,Interrupt并不会终止处于“运行状态”的线程,其仅仅是对标志位做了修改
Thread thread = new Thread(new Runnable() { @Override public void run() { int i = 0; while (i<10){ System.out.println(i++); } try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("睡眠结束"); } }); thread.start(); thread.interrupt(); }
方法:
//void setDaemon(boolean on) 设置守护线程 参数:true:设置为守护线程 false:非守护线程。默认false
// boolean isDaemon() 判断当前线程是否是守护线程:true:表示守护线程 false:用户线程
java中有两种线程,用户线程和守护线程,可以通过isDaemon()来区分线程是否是守护线程
用户线程一般是用来执行用户级任务
守护线程也称之为“后台线程”,服务于用户线程,一般用来执行后台任务 例如“:垃圾回收线程是单独用来处理无用对象的回收的, 负责垃圾回收的线程就是守护线程
守护线程的生命周期:
守护线程的生命周期是依赖于用户线程,当用户线程存在,守护线程就会存活,当用户线程生命终止,守护线程的也会随之消亡
线程优先级:指导线程的执行的先后顺序的
方法:
//int getPriority() 获取线程的优先级
//setPriority(int newPriority) 设置线程优先级 newPriority必须在1~10之间的整的,默认的是5
优先级特点:
1、java线程的优先级并不绝对,他所控制的是执行的优先机会,优先级的决定权在操作系统,java设置的优先级只能是被优先执行的概率会高一些,并不绝对
2、java中优先级共有10级,分为1-10,数值越大,表明优先级越高,一般普通的线程优先级是5
3、优先级具有继承性,如果一个线程B在另一个线程A中创建出来,那么线程B的优先级和线程A保持一致