java多线程解说【叁】_Thread的常用API实现

上篇文章:java多线程解说【贰】_java内存模型


在上文中我们分析了java内存模型和volatile、synchronized的实现原理。在这篇文章中,我们继续分析一下Thread的常用api有哪些,以及它们是如何实现的。


Thread的结构


我们先通过源码看看Thread中主要封装了哪些对象:


private char        name[];    //线程的名称
private int         priority;    //线程的优先级
private boolean     daemon = false;    //该线程是否为守护线程,默认为false
private Runnable target;    //该线程要执行的任务
private ThreadGroup group;    //该线程归属的线程组
private ClassLoader contextClassLoader;    //加载器,默认为AppClassLoader
private static int threadInitNumber;    //数字标识匿名线程
ThreadLocal.ThreadLocalMap threadLocals = null;    //线程私有变量
private long stackSize;    //分配给线程的栈空间大小,默认0(不限制)
private long tid;    //线程id
private static long threadSeqNumber;    //线程序列
private volatile int threadStatus = 0;    //线程运行状态,默认是0(NEW)

volatile Object parkBlocker;    //java.util.concurrent.locks.LockSupport.park使用
private volatile Interruptible blocker;    //枚举字段,interrupt方法使用
private final Object blockerLock = new Object();    //更改blocker值时使用,作为锁的对象


Thread的构造方法


其完整的构造方法声明如下:

public Thread(ThreadGroup group, Runnable target, String name, long stackSize);


其中,ThreadGroup如果不指定,则为当前线程(即启动该线程的线程)的ThreadGroup;Runnable就是该线程将要执行的类,分两种情况,一种是继承了Thread类,一种是实现了Runnable接口;name就是线程的名称,如果不指定则为"Thread-索引号(索引从0开始)";stackSize是JVM分配给线程的栈空间大小,默认0(不限制)。


Thread关于自身信息的API


setName(String name)/getName()

读写线程名称


getThreadGroup()

读线程组


activeCount()

获取当前线程所在线程组上的存活线程


setDaemon(boolean on)

设置当前线程为守护线程。守护线程不应执行重要的任务,一般用于记录日志或监控之用,因为jvm当只有守护线程在运行时就停止


isDaemon()

判断该线程是否是守护线程


checkAccess()

判断当前线程是否有权限去操作该线程


holdsLock(Object obj)

判断该线程是否持有某对象的锁


getId()

获取当前jvm中该线程的唯一标示


isAlive()

判断该线程是否存活,标准是线程已启动但还没有执行完毕


getState()

获取该线程状态,返回值为枚举,包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED



Thread关于执行的API


start()

正确的启动一个线程的方法。先完成一些初始化动作,然后会通知JVM调用线程的run()方法


run()

只是单纯地执行线程代码,并没有启动一个新的线程。


join(long millis, int nanos)

保证指定时间以内,在JVM中只有该线程在运行。millis是等待的毫秒数,nanos是微秒数(参数可省)。如果millis填0,则一直等到当前线程执行完毕,JVM才会调度其他线程执行。

exit()

线程运行结束之前做下自身资源清理工作


yield()

当该线程让出CPU,给其他线程一个获取调度的机会,但是不确保一定会调度到其他线程上。


sleep(long millis, int nanos)

线程在指定时间以内休眠,需要注意的是在休眠过程中该线程不会释放持有的锁。millis是等待的毫秒数,nanos是微秒数(参数可省)。


interrupt()
它不会中断一个正在运行的线程,实际上是在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被wait、join或sleep阻塞时,那么它将接收到一个中断异常(InterruptedException),我们可以在异常块里调用本方法,从而提早地终结被阻塞状态。如果线程没有被阻塞,这时调用interrupt()将不起作用,仅仅是设置中断标志位为true的情况

interrupted()

判断该线程中断标识是否为true,返回该标识并将标识置为false


isInterrupted()

判断该线程中断标识是否为true,返回该标识。其实该方法和interrupted()方法底层调用的都是isInterrupted(boolean isClearState),只不过参数不同而已


Thread API中不鼓励使用的方法


setPriority(int newPriority)/getPriority()

读写线程的优先级。关于优先级有三个枚举值:
MIN_PRIORITY = 1;
NORM_PRIORITY = 5;
MAX_PRIORITY = 10;

数据越大,优先级越高。但是这个方法不推荐使用,是因为并不是所有的JVM都会严格按照该优先级的设定而调度线程,而且在有的JVM中,当一个线程的优先级设置过高会导致只运行该线程,在该线程运行完之前不会调度到其他线程上



suspend()/resume()

暂停/唤醒该线程。也不推荐使用,因为暂停并不释放锁,可能导致死锁;而且暂停的线程状态仍然是RUNNABLE,排查问题很难


destroy()

销毁该线程,但没有进行清理工作。线程持有的锁(monitor)不会释放


stop(Throwable obj)

停止线程,没有进行清理工作。线程持有的锁(monitor)不会释放



下篇文章:java多线程解说【肆】_锁实现:wait()/notify()


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值