《Java 7 Concurrency Cookbook 读书笔记》线程管理

java中创建线程有2种方式:

  1.继承Thread类,覆盖run方法。
  2.构建实现Runnable接口类,然后创建一个Thread类对象传入一个Runnable对象作为构造参数。

获取和设置线程信息:

 ID: 每个线程的独特标识。
 Name: 线程的名称。
 Priority: 线程对象的优先级。优先级别在1-10之间,1是最低级,10是最高级。
 Status: 线程的状态。
 Tips:
 setPriority() 方法会抛出 IllegalArgumentException 异常,如果设置的优先级不是在1-10之间。
 在Java中,线程只能有这6种中的一种状态:  new, runnable, blocked, waiting,
 time waiting, 或 terminated。

线程的中断:

   Thread类有一个boolean类型的属性表明线程是否被中断,当调用线程的interrupt()方法,
   此属性被设置为true,isInterrupted() 方法仅返回属性值。

   isInterrupted()和interrupted()区别:
   isInterrupted()不会改变interrupted属性值,interrupted()会设置为false,
   interrupted() 方法是一个静态方法,建议使用isInterrupted()方法。

操作线程的中断机制

   在Thread类的run方法中捕获InterruptedException异常来控制线程的中断。

    private void do() throws InterruptedException
    { 
     //....
     if (Thread.interrupted()) {
    throw new InterruptedException();
     }
     }
      @Override
      public void run() {
       try {
      do();
      } catch (InterruptedException e) {

    } 
    }

线程的睡眠与恢复

  Thread类的 sleep(long millis) 方法 。表示线程休眠millis毫秒。
  TimeUnit枚举元素的sleep(long millis)方法同样能使当前线程睡眠millis毫秒。
  2种线程休眠的方法都会抛出InterruptedException异常。

等待线程的终结

  当前线程调用某个线程的join()方法,当前线程会暂停直到被调用线程执行完成。
  join (long milliseconds)
  join (long milliseconds, long nanos)

  ex:thread1调用thread2.join(1000),那么thread1暂停运行,
  直到一下其中一个条件发生,join方法返回:
  thread2结束运行
  1000毫秒过去了

守护线程的创建和运行

  在Java中有两类线程:用户线程 (User Thread)、守护线程 (Daemon Thread)。

  守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,
  比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。
  因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。
  反过来说,只要任何非守护线程还在运行,程序就不会终止。

  Thread类的 setDaemon() 方法设置线程为守护线程,此方法必须在调用start()方法之前调用。
  isDaemon() 方法来检查线程是否是守护线程(方法返回 true) 或者是用户线程 (方法返回 false)。

处理线程非检测异常

  Java中有2种异常:
  检测异常(Checked Exceptions):这种异常必须强制捕获或者继续抛出异常(throws)。
  非检测异常(Unchecked Exceptions):这种异常无需强制捕获。
  在线程对象run()方法中抛出一个检测异常必须捕获,因为run()方法不接受throws抛出异常。

  在Java处理Thread中的非检测异常类,需要实现UncaughtExceptionHandler接口。
  public class ExceptionHandler implements UncaughtExceptionHandler {

  @Override
  public void uncaughtException(Thread t, Throwable e) {

 }
 }
 在线程启动之前设置setUncaughtExceptionHandler(new ExceptionHandler());

当在一个线程里抛出一个异常,但是这个异常没有被捕获(非检查异常), 
JVM 检查线程的相关方法是否有设置一个未捕捉异常的处理者 。
如果有JVM使用Thread对象和Exception作为参数调用此方法 。
如果线程没有捕捉未捕获异常的处理者, 那么JVM会把异常的 stack trace 写入操控台并结束任务。
静态方法 setDefaultUncaughtExceptionHandler() 为应用里的所有线程对象建立异常handler 。
JVM检测异常3种潜在的Handler:Thread UncaughtExceptionHandler->
Thread Group UncaughtExceptionHandler->Default Thread 
UncaughtExceptionHandler->print stack trace

本地线程变量

ThreadLocal类为线程的变量存储独立的属性值。
ThreadLocal<Object> threadLocal = new ThreadLocal<Object>() {
    //初始值
    protected Object initialValue() {
        return new Object();
    };

    public void set(Object value) {
    };

    public Object get() {
        return new Object();
    };
    //移除此线程局部变量的值。
    public void remove() {
    };

}; 
InheritableThreadLocal 类提供线程创建线程的值的遗传性 。
如果线程A有一个本地线程变量,然后它创建了另一个线程B,
那么线程B将有与A相同的本地线程变量值。
你可以覆盖 childValue() 方法来初始子线程的本地线程变量的值。
它接收父线程的本地线程变量作为参数。
InheritableThreadLocal<Object> inheritableThreadLocal = 
new InheritableThreadLocal<Object>() {
    protected Object childValue(Object parentValue) {
        return parentValue;
    };
};

线程组

Java提供ThreadGroup类来组织线程。 
ThreadGroup对象可以由Thread对象组成和由另外的ThreadGroup对象组成,生成线程树结构。
ThreadGroup threadGroup = new ThreadGroup(group name);
Thread thread=new Thread(threadGroup, runnableimpl);
activeCount() 和 enumerate() 方法来获取线程个数和与ThreadGroup对象关联的线程的列表。

处理线程组内非检测异常

public class MyThreadGroup extends ThreadGroup {
public MyThreadGroup(String name) {
super(name);
}
@Override
public void uncaughtException(Thread t, Throwable e) {
//覆盖此方法
}
}

线程工厂

ThreadFactory线程工厂。
ThreadFactory 接口只有一个方法是newThread。它接收 Runnable 对象作为参数并返回一个 Thread对象。
public class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
    return new Thread(r);
}
}