Java使用Thread类来代表或者是运行一个线程,使用Runnable接口表示一个线程任务
Thread.interrupted()方法:调用该方法时候,线程的中断位置被置位,可以使用Thread的静态方法currentThread方法获得当前线程,然后调用isInterrupted 方法;
但是在线程被阻塞的时候,就无法检测中断状态。这是产生InterruptedException的地方,当在一个被阻塞的线程(调用了wait和sleep)上调用interrupted方法时候,阻塞调用将会被InterruptedException异常打断。(但是存在不被中断的阻塞IO调用)。
在中断被置位的时候调用sleep方法,它不会休眠。相反,它将清除这个状态并抛出InterruptedException
可以注意到,一个类的静态方法,一个是实例Thread及其子类的方法
Java线程的六种状态
1、New(新生):用new 操作符创建了新线程之后,在线程还没调用start()方法之前
2、Runnable(运行):调用了Thread的start()方法之后
3、Blocked(被阻塞):(被阻塞和等待的线程)当一个线程试图获取一个内部的对象锁,但是该锁被其他线程所持有,该线程进入阻塞状态
4、Waiting(等待):一个线程需要另一个线程完成任务后才可以进行他的任务
5、Timed waiting(计时等待):有一些方法的调用可以导致线程进入计时等待,这些方法有Thread静态方法sleep,Object.wait,Thread.join,Lock.tryLock,以及Condition.await计时版本
6、Terminated(被终止):run方法正常结束,因为一个没有捕捉的异常终止了run方法而意外死亡
Java线程的优先级和守护线程(弱线程)。
这里给出Object类的中跟线程调度有关的方法wait,notify,notifyAll,调用该对象的的方法时候,必须要先获得该对象的锁,不然会抛出IllegalMonitorStateException
线程的同步:并发操作如果如果不进行同步操作,会得到操作的不一致
使用ReentrantLock类和关键字synchronized进行临界区的访问
代码模板
ReentrantLock lock = new ReentrantLock();
public void run(){
try{
lock.lock();
}catch(Exception ex){
}finally{
lock.unlock();
}
}
这种操作跟synchronized对整个对象或者方法的写法上类似,因为每一个对象上都有一个内部锁,并且该锁有一个内部条件。由锁来管理那些试图进入synchronized的代码块的线程
Object lock = new Object();
public void run(){
synchronized(lock){
}
}
当线程获得对象锁的时候,发现当前条件不满足,就需要阻塞当前线程并让出对象锁
条件对象:
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void run(){
try{
while(条件不满足)
condition.await();
condition.signalAll();
}catch(Exception ex){
}finally{
lock.unlock();
}
}
当一个线程被调用await的时候,必须有其他线程调用signalAll才有可能使其唤醒,调用signalAll不会立即激活一个等待的线程,它仅仅解除等待线程的阻塞,以便这些线程可以在当前线程退出同步方法后,通过竞争的方法实现对对象的访问。
注意:当一个线程拥有某个条件的锁的时候,它仅仅可以在该条件上调用await,signalAll或者signal方法。
Object方法
void wait: 调用该对象notify方法的线程首先要获得该Object的对象锁,否则会抛出IllegalMonitorStateException,调用该方法后线程进入阻塞状态,知道有其他的线程调用该Object的notify方法
void notifyAll ,解除那些在Object对象上面调用wait方法的所有线程的阻塞状态
void wait (long time),导致线程进入等待状态直到有其他线程通知他
volatile关键字为实例域的同步访问提供了一种免锁的机制,java对设计该实例域的操作的时候不会重拍该指令
锁测试和超时
ReentrantLock的lock方法是不能被中断的,如果一个线程在等待一个锁时候被中断,中断线程在获得锁之前是一直处于阻塞状态,如果出现死锁,那么lock方法将无法终止
然而,如果使用带有超时参数的tryLock,即便线程在等待期间被中断,将抛出InterruptedException 异常,这个属性运行他打破死锁,而lockInterruptibly方法相当于一个超时设为无限的tryLock方法
读写锁
jdk5新增的ReentrantLock类和ReentrantReadWriteLock,
ReentrantReadWriteLock, 可以使用其readLock和writeLock获得读锁和写锁
启用stop和suspend方法的原因:可能会导致出现不一致的问题。
如果希望终止一个线程,就应该中断线程,被中断的线程会在安全的时候停止