start():启动线程
start方法启动一个新线程,start方法首先调用才能创建子线程,不能重复使用
public synchronized void start() { group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { } } } private native void start0();//调用native方法
启动方法是需要底层OS来启动子线程,start是间接启动。
native方法说明:
JNI:Java native interface,java本地方法接口(JMM中存在本地方法栈),调度系统本身的提供的非Java代码(C/C++代码)。
run():子线程的执行体
整个子线程执行的业务逻辑都在run方法中;单独调用run方法,会在当前的线程中执行run()操作,和普通方法调用是一样的,不会启动子线程,run方法可以重复调用。Thread类中的run方法只是判断任务体Runable是否存在,未做其他业务,继承Thread是需要重写。
start()和run()方法的区别:
start()方法是用来启动子线程,start方法启动子线程后自动的来调用run方法。
run()方法是子线程的业务执行体,不能直接调用run方法(通过调用run方法是不能操作子线程的),直接调用和普通方法一样。
yield():线程让步
方法在thread类中,是Thread类中静态方法,是用来暂停当前线程的执行,并且让步于其他相同优先级或更高优先级的线程先执行。
方法特点:
1、yield方法让步CPU的资源,让给谁由系统决定的,一般是让给相同优先级或者更高优先级的线程获得执行权,如果没有的话,会执行原来的线程
2、yield让步:会让当前线程由“运行状态”进入到“就绪状态”,就绪状态的线程会按照优先级进行调度,等待CPU的调度。
3、yield让步CPU资源后,线程不会释放锁。
join():线程合并(插队)
暂停当前线程执行,等待子线程的执行,也叫做线程合并,join方式是将并行执行的线程合并成串行执行,例:在线程ta中调用tb.join,会暂停ta的执行,先让tb执行完毕,ta才会执行。
方法介绍:
t.join() 允许t线程在当前线程之前执行,待t线程执行结束后当前线程再执行。
t.join(long millis)(时间单位:毫秒)允许t线程在当前线程之前执行,且最长时间millis毫秒之后,当前线程才能执行。
t.join(long millis, int nanos)与t.join(long)一样,只不过可以提供纳秒级的精度。
方法特点:
1、join方法是thread类中的方法,会抛出InterruptedException中断异常
2、当前线程ta中tb.join,tb会执行,ta线程会进入WAITING或TIMED_WAITING状态。
3、当前线程ta中tb.join,则ta线程会释放当前持有的锁,join方法实现是通过wait/notify线程通信方式来实现的,wait方法的使用会释放锁。
//一直等待子线程 public final void join() throws InterruptedException { join(0); } //提供毫秒,纳秒级别的等待时间 public final synchronized void join(long millis, int nanos) throws InterruptedException { if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } //纳秒的处理最终转换为毫秒处理 join(millis); } //提供毫秒级别的等待时间 public final synchronized void join(long millis)throws InterruptedException { if (millis == 0) { //millis=0,会一直判断子线程是否结束,否则会一直等待 while (isAlive()) { //线程等待 wait(0); } } else { //判断子线程是否结束且是否到达指定的毫秒数,否则会等待 while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); } } }
interrupt():中断线程
用来中断当前线程,终止处于“阻塞状态”的线程
方法介绍:
该方法在Thread类中,是一个普通方法,由对象调用该方法。
boolean isInterrupted() 判断是否发送了中断操作, true:发生中断操作 false:未发生中断操作
方法特点:
1、如果当前线程是可中断的阻塞状态(join、sleep、wait)等方法会导致线程进入阻塞撞状态:WATING / TIMED_WAITING状态),在任意其他的线程中调用interruprt方法,那么会立即抛出InterruptedException来停止的阻塞状态
2、如果当前线程是可运行状态。调用interruprt方法,线程还是会继续执行,直到发生了sleep、join、wait等方法的调用,才会在进入阻塞之后,随后立即抛出InterruptedException,跳出阻塞状态
public void interrupt() { synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // Just to set the interrupt flag 注意这句 b.interrupt(this); return; } } interrupt0(); } private native void interrupt0(); //JNI方法,中断操作由系统来提供中断的方式
sleep():线程休眠
会让线程休眠,而且哪个线程调用,哪个线程休眠 ,TimeUtil.sleep(long),Thread.sleep、或当前的线程t.sleep,其结果都是当前的线程休眠。
方法介绍:
sleep(long millis)
sleep(long millis, int nanos)
都是提供休眠操作,时间单位粒度不同
sleep 是Thread类提供的方法,会抛出InterruptedException异常
方法特点:
1、sleep休眠期间,会让出CPU使用权,但线程仍然持有锁。(抱着资源睡觉)
2、sleep休眠时间到了之后,不会立即执行,而是线程由“阻塞状态”进入到“就绪状态”。
public static native void sleep(long millis) throws InterruptedException //JNI public static void sleep(long millis, int nanos) throws InterruptedException { if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep(millis); }
deamon:守护线程
方法介绍:
setDaemon(boolean on) 设置线程为守护线程 true:表示是守护线程 false:非守护线程 默认false
boolean isDaemon():判断当前线程是否是守护线程 true(守护线程)。
Java中的线程主要有两种:用户线程和守护线程。
守护线程和用户线程:
用户线程:一般用户执行的用户级的线程。
守护线程:也叫做后台线程,脱离于终端,用来服务于用户线程。 例如:GC是一个单独的线程处理,GC线程就是一个守护线程。
守护线程的生命周期:
依赖于用户线程,当有用户线程存在,守护线程就会存活,当没有用户线程存在,那守护线程也随之消亡,需要注意的是:Java虚拟机在“用户线程”都结束后会后退出。
public final void setDaemon(boolean on) { checkAccess(); if (isAlive()) { throw new IllegalThreadStateException(); } daemon = on; } public final boolean isDaemon() { return daemon; }
Priority:线程的优先级
线程优先级,顾名思义:就是来指导线程的执行优先级的
方法介绍:
int getPriority() 获取优先级
setPriority(int newPriority) 设置优先级
方法特点:
1、java线程的优先级并不绝对,它所控制的是执行的机会,也就是说,优先级高的线程执行的概率比较大,而优先级低的线程也并不是没有机会,只是执行的概率相对低一些。
2、Java线程一共有10个优先级,分别为1-10,数值越大,表明优先级越高,一个普通的线程,其优先级为5(默认);线程的优先级具有继承性,如果一个线程B是在另一个线程A中创建的,则B叫做A的子线程,B的初始优先级与A保持一致。
public final int getPriority() { return priority; } public final void setPriority(int newPriority) { ThreadGroup g; checkAccess(); if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); } if((g = getThreadGroup()) != null) { if (newPriority > g.getMaxPriority()) { newPriority = g.getMaxPriority(); } setPriority0(priority = newPriority); } } private native void setPriority0(int newPriority); //JNI