线程管理读书笔记

来源:互联网 发布:linux shell替换字符串 编辑:程序博客网 时间:2024/04/30 02:03

线程的创建和运行

1.创建一个实现Runnable接口的类。使用带参数的Thread构造器来创建Thread对象。这个参数就是实现Runnable接口的类的一个对象。

2.继承Thread类,并且覆盖run()方法。

调用Thread的start()方法即可运行线程,运行的内容就是run()方法的方法体。

当一个程序的所有非守护(non-daemon)线程都运行完成的时候,这个Java程序将宣告结束。

线程信息的获取和运行

ID         线程的唯一标志符

Name  线程名称

Priority 线程对象的优先级 线程优先级是1到10

Status  线程的状态 6种状态:new,runnable, blocked, waiting time waiting, terminated。



当我们new完Thread对象后,线程就进入了初始状态new

对象调用了start()方法,就进入了可运行Runnable状态

进入Runnable状态后获取到CPU的时间片就会进入running状态

进入running状态后,如果run方法执行完成,或者程序结束则会进入terminated状态

进入running状态后,如果自身调用sleep方法或者其他线程调用join方法,则当前线程会进入阻塞(blocked)状态(但不会释放所占有的资源),sleep结束或者join结束,则会进入Runnable状态,等待获取cpu时间。

进入running状态后,当线程调用了yield()方法,意思是放弃当前获得的cpu时间片,则回到可运行状态。

进入Runnable状态后,发现调用的资源要被synchronized,同时获取不到锁标记,就会进入到锁池状态,等待获取锁标记(是队列,先到先得)。一旦获取到锁标记则进入Runnable状态,等待os分配时间片。

当线程调用wait方法后会进入等待队列(这时会释放线程占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或者notifyAll()方法(由于notify()只是唤醒一个线程,我们就不能确定具体唤醒 的是哪一个线程,那么我们需要唤醒的线程可能不能够被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程)才能唤醒。唤醒后线程会进入锁池,等待获取锁标记。


线程信息中断

interrupt();

判断线程是否中断,isInterrupted();

静态Thread.interrupted();


线程的休眠和恢复

sleep() 休眠

yield() 放弃CPU时间

等待线程的终止

在一些情形下,我们必须等待线程终止。例如,我们的程序在执行其他的任务时,必须先初始化一些必须的资源。可以使用线程来完成这些初始任务,

等待线程终止,再执行程序的其他任务。为了达到这个目的,我们使用Thread的join方法。

守护线程的创建和运行

Java里有一种特殊的线程叫做守护(Daemon)线程。这种线程的优先级很低,通常来说,当同一个应用程序里没有其他线程运行的时候,守护线程才运行。

当守护线程是程序中唯一运行的线程时,守护线程执行结束后,JVM也就结束了这个程序。

具体方法是setDaemon(true);必须在线程start之前执行!一旦线程开始运行,将不能再修改守护状态。。isDaemon()方法用来检查一个线程是否是守护线程。

线程中不可控异常的处理

因为run方法不支持throws语句,所以当线程对象的run()方法抛出非运行异常时,我们必须捕获并且处理它们。当运行时异常从run()方法中抛出时,默认行为是在控制台输出堆栈记录并且退出程序。

实现上是设置ExceptionHandler,setUncaughtExceptionHandler(new ExceptionHandler()),个人认为应该在start()之前设置。

实现UncaughtExceptionHandler类,并完成uncaughtException(Thread t, Throwable e)方法。

还有一个静态方法setDefaultUncaughtExceptionHandler。

如果线程抛出一个未捕获的异常时,JVM将为异常寻找以下三种可能的处理器:

首先,查找线程对象的未捕获异常处理器,如果找不到,JVM将继续查找线程对象所在线程组(ThreadGroup)的未捕获异常处理器,如果还是找不到,JVM将继续查找默认的未捕获异常处理器。如果没有一个处理器的存在,JVM则将堆栈异常记录打印到控制台,并退出程序。

线程局部变量的使用

如果一个对象的属性不需要被所有线程共享,Java并发API提供了一个干净的机制,即线程局部变量(Thread-Local Variable)。

public static ThreadLocal<Date> startDate = new ThreadLocal<Date>(){

protected Date initialValue(){

return new Date();

}

使用:startDate .get(),第一次调用时如果还没有设置值则会执行initalValue()方法。

继续学习:InheritableThreadLocal

线程的分组

ThreadGroup group = new ThreadGroup("group");

然后在创建Thread时:Thread thread = new Thread(group, runnable);

group.activeCount();  //Returns an estimate of the number of active threads in this thread group.

线程组中不可控异常的处理

在ThreadGroup类中,override uncaughtException方法,设置捕获未处理异常的执行逻辑。

使用工厂类创建线程

接口ThreadFactory,并实现newThread方法。

0 0
原创粉丝点击