线程的状态
- NEW
- RUNNABLE
- BLOCKED:线程阻塞于锁
- WAITING:等待状态,当前线程需要等待其他线程通知或者中断才能被唤醒。
- TIME_WAITING:超时等待,与waiting状态不同的是,它可以在指定的时间到达时返回到运行状态,不一定需要别的线程的唤醒。
- TERMINATED
线程状态变迁
- 从RUNNABLE变为WAITING状态可能的情况
object.wait();//等待object.notify()或者object.notifyAll();
threadA.join();//等待线程threadA执行完毕
LockSupport.park();//important,等待相应的uppark调用。
- 从RUNNABLE到TIME_WAITING类似于上,只是加上了超时返回。
Thread.sleep(long);
object.wait(long);
threadA.join(long);
LockSupport.park(long);
- 从RUNNABLE到阻塞状态
等待进入synchronized方法和synchronized代码块。注意:阻塞在concurrent包中的Lock接口的线程是等待状态(因为底层使用的LockSupport类中的方法)
线程的创建与销毁
线程的创建
新建一个线程对象时:init方法会从其父线程(当前线程)继承一些信息,比较重要的有(contextClassLoader,daemon,priority,可继承的ThreadLocal)
线程的启动
thread.start();
中断
中断就相当与线程与线程之间发消息一样,假如threadA中调用threadB.interrupt(), 那么threadB就会收到这个中断消息并做出响应(比如,threadB正在sleep,那么sleep会马上结束并抛出InterruptedException)
对thread.isInterrupted()和Thread.interrupted(检查当前线程中断表示位)的返回值取决与线程是否还有未被处理的中断消息。对于上面的例子来说,thread.isInterrupted()返回false,因为中断消息已经被消耗了(返回InterruptedException)
安全的终止线程demo
通过这个Runner生成的线程对象可以通过中断关闭,或者cancel()调用关闭
private static class Runner implements Runnable{
private volatile boolean on = true;
@Override
public void run() {
while (on && !Thread.currentThread().isInterrupted()){
//do
}
}
public void cancel() {
on = false;
}
}
线程间通信
volatile和synchronized关键字的内存语义
等待通知机制
这里主要涉及Object类的几个方法
wait();
wait(long);//超时等待
notify();
notifyAll();
这里以一段生产者消费者代码,这样写有点冗余。
private class Container{
private int maxCap;
private int curCap;
private int toPut;
private int toGet;
private int[] data;
Container(int cap){
this.maxCap = cap;
data = new int[cap];
curCap = toGet = toPut = 0;
}
public int get(){
synchronized (this){
while (curCap <= 0)
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
int tmp = data[toGet];
curCap--;
toGet = toGet + 1 < maxCap ? toGet + 1: 0;
this.notifyAll();//this can notify the consumer thread also.
return tmp;
}
}
public void put(int i){
synchronized (this){
while (curCap == maxCap){
try{
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data[toPut] = i;
curCap ++;
toPut = toPut + 1 < maxCap ? toPut + 1 : 0;
this.notifyAll();
}
}
}
Thread.join()
如在threadA中调用threadB.join()那么就会等threadB返回之后才执行A线程中threadB.join()之后的内容。
这里其实是相当于 threadB.wait(); 然后线程销毁时threadB.notifyAll();
ThreadLocal
ThreadLocal中存储的键值对绑定到线程,当其中的值不再使用时需要置空以便垃圾回收
。可以用于方法调用计时。