线程信息
Thread保存了一些属性信息,有助于我们区分、了解其状态和控制其优先级。
ID : 线程的唯一标识
Name:线程名称
Priority:优先级,值在1~10之间,值越小优先级越低。
Status:线程的状态:new,runnable,blocked,waiting,time waiting,或terminated
Thread.currentThread().getName()
thread.setPriority(Thread.MAX_PRIORITY)//优先级
thread.getState() //线程状态
thread.getId()#线程ID
//State.TERMINATED,线程状态状态枚举,状态和ID没有set方法
线程中断
有时候,用户需要终止应用程序或一个任务。每一个线程都有一个属性存储boolean值,表明是否被中断。
isInterrupted()//检测线程是否被中断
interrupt() //设置中断属性为true
Thread.interrupted() //静态方法,设置中断属性为false
控制线程中断
如果线程实现复杂的逻辑,划分为多个函数,或它有递归调用,我们能使用更好的机制来控制线程的中断:InterruptedException。当探测线程被中断后跑出InterruptedException异常,并且在run方法中捕获它。
public void run() {
File file = new File(initPath);
if (file.isDirectory()) {
try {
directoryProcess(file);
} catch (InterruptedException e) {
System.out.printf("%s: The search has been
interrupted",Thread.currentThread().getName());
}
}
}
private void directoryProcess(File file) throws
InterruptedException {
File list[] = file.listFiles();
if (list != null) {
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
directoryProcess(list[i]);
} else {
fileProcess(list[i]);
}
}
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
休眠或挂起线程
thread.sleep();//接受整数作为参数,单位毫秒,当调用结束后,会分配CPU时间给它
TimeUnit.SECONDS.sleep(5);//睡眠5秒
等待线程结束
thread.join()//无限制挂起调用线程的执行,直到被调用对象执行完成
//挂起线程,直到被调用对象执行完成或过了milliseconds指定时间
join (long milliseconds)
join (long milliseconds, long nanos)
守护进程
Java中守护进程是一类优先级很低,在同一程序中仅在没有其他线程执行时才被执行的线程。当JVM中仅剩下这类守护进程运行时,就回退出。由于这些特性,守护进程通常被用来为运行在同一程序中normal线程提供服务,他们通常无限循环等待服务请求,他们不会做重要的工作,因为我们无法知道它什么时候才能获得CPU时间。
thread.setDaemon(true);
处理thread中不可控线程
Java中存在两种异常:checked exception,必须在方法用throws声明或在方法内部捕获,例如IOException。Unchecked exception,没有必要指定或捕获,例如NumberFormatExecption。一旦checked exception在run()方法中抛出,默认行为将异常加入stack trace,退出。
public class ExceptionHandler implements UncaughtExceptionHandler
{
public void uncaughtException(Thread t, Throwable e) {
System.out.printf("An exception has been captured\n");
System.out.printf("Thread: %s\n",t.getId());
System.out.printf("Exception: %s: %s\n",e.getClass().
getName(),e.getMessage());
System.out.printf("Stack Trace: \n");
e.printStackTrace(System.out);
System.out.printf("Thread status: %s\n",t.getState());
}
}
thread.setUncaughtExceptionHandler(new ExceptionHandler());//设置异常处理器
Thread.setDefaultUncaughtExceptionHandler();//静态方法,设置所有线程的异常处理器
线程本地变量
本地线程变量为每个线程存储一个属性值,你可以使用get()方法读取,用set()方法修改这个值。第一次访问这个本地线程变量值,若没有这个属性值,调用initialValue()方法分配给次线程。
ThreadLocal<Date> startDate= new ThreadLocal<Date>() {
protected Date initialValue(){
return new Date();
}
};
线程组
Java concurrency API允许我们将多个线程作为一个单个单元,并提供方法访问这些线程,并操作它们。
ThreadGroup threadGroup = new ThreadGroup("Searcher");//新建线程组
for (int i=0; i<5; i++) {
Thread thread=new Thread(threadGroup, searchTask);
thread.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
threadGroup.activeCount()//活动线程数
threadGroup.list()//列出线程信息
Thread[] threads=new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);//访问线程,并操作
for (int i=0; i<threadGroup.activeCount(); i++) {
System.out.printf("Thread %s: %s\n",threads[i].
getName(),threads[i].getState());
}
处理线程组异常
处理线程组内任何线程抛出的异常。
public class MyThreadGroup extends ThreadGroup {
public MyThreadGroup(String name) {
super(name);
}
@Override
public void uncaughtException(Thread t, Throwable e) {//覆盖uncaughtException方法
System.out.printf("The thread %s has thrown an Exception\n",t.
getId());
e.printStackTrace(System.out);
System.out.printf("Terminating the rest of the Threads\n");
interrupt();
}
}
使用工厂方法创建线程
实现ThreadFactory接口即可