Thread和ThreadGroup、线程状态初探
ThreadGroup是为了方便对Thread进行管理,ThreadGroup中可以有ThreadGroup和Thread,所以成树形结构。
Thread中有很多方法都是native的,Thread实例化的时候,其实就只是简单的设置了一些变量,比如线程组、优先级、Runnable等,这个时候线程是“NEW”状态。然后调用start方法的时候,才真正执行动作,比如把线程放到线程组里、执行nativeCreate,然后VM才会执行run方法,线程处于“RUNNABLE”状态。
Thread中一些重要的方法,简单说明一下:
run方法:是启动线程后,被JVM调用的。我们出入的Runnable在这里被调用
start方法:启动线程
sleep系列方法:有三个,需要注意的是,它们都是类方法
public static void sleep(long millis) throws InterruptedException
public static void sleep(long millis, int nanos) throws InterruptedException
private static native void sleep(Object lock, long millis, int nanos) throws InterruptedException
这个方法可以让当前线程休眠,其实是进入了是了“TIMED_WAITING”状态。比如,我们在主线程中调用sleep方法(说明一下,主线程的工作也是运行在run方法内的,主线程中调用sleep方法,意思就是主线程的run方法中调用sleep方法),会让主线程休眠,此时主线程不会放弃任何monitor lock。我们看sleep中的源码,是获取了当前线程中的lock变量,把它当作monitor lock,调用了native sleep。其它线程中调用sleep也是一样的。
join系列方法:有三个,其中带一个参数和两个参数的方法中有同步代码块
public final void join() throws InterruptedException
public final void join(long millis) throws InterruptedException
public final void join(long millis, int nanos) throws InterruptedException
看join的实现,其实是对Object wait方法的封装,方便使用而已。设计很好,因为join是属于Thread实例(比如A)的方法,它在另一个线程中被调用,比如在主线程中调用,由于join的实现是把A的lock变量作为monitor lock,然后调用了lock.wai()方法,这样主线程就进入了“WAITING”状态,如果是wait有传参数,是进入“TIMED_WAITING”状态,monitor被释放了。join的注释说,A线程结束的时候,会调用notifyAll方法(具体怎么调用的目前不知道。。。),这样主线程就会被唤醒继续执行。
/** * Waits at most {@code millis} milliseconds for this thread to * die. A timeout of {@code 0} means to wait forever. * * <p> This implementation uses a loop of {@code this.wait} calls * conditioned on {@code this.isAlive}. As a thread terminates the * {@code this.notifyAll} method is invoked. It is recommended that * applications not use {@code wait}, {@code notify}, or * {@code notifyAll} on {@code Thread} instances. * * @param millis * the time to wait in milliseconds * * @throws IllegalArgumentException * if the value of {@code millis} is negative * * @throws InterruptedException * if any thread has interrupted the current thread. The * <i>interrupted status</i> of the current thread is * cleared when this exception is thrown. */
通过分析join我们知道,join给我们提供了一种让一个线程先等待另一个线程执行完再继续执行的机制。其实在Android 的HandlerThread 的getLooper方法,和join原理是一样的,看看java线程同步粗浅学习
再啰嗦一下,join翻译成中文的意思是加入,就好像,我们执行主线程,new了一个子线程A,调用了A的join方法,就把A加入到主线程中了,等A执行完,主线程继续执行。这个只是感觉上的理解,具体原理是上面的讲解。
yield方法:这个是个native 的static方法,让步的意思
这个方法一般不会在实际开发中遇到,这个方法会让当前线程让出CPU的时间片,然后当前线程和其它线程又同时竞争CPU
Thread的状态
上面这张图很棒,把线程的各种状态描述的很清楚。
具体可以看下面这篇文章线程的状态转换以及基本操作