Java的多线程调度是一种抢占机制,
抢先式调度又分为:时间片方式和独占方式。在时间片方式下,当前活动线程执行完当前时间片后,如果有其他处于就绪状态的相同优先级的线程,系统会将执行权交给其他就绪态的同优先级线程;当前活动线程转入等待执行队列,等待下一个时间片的调度。
在独占方式下,当前活动线程一旦获得执行权,将一直执行下去,直到执行完毕或由于某种原因主动放弃CPU,或者是有一高优先级的线程处于就绪状态。
比如说,线程会争抢CPU的时间片。有的抢到了,就是可运行状态(可能正在执行),如果资源是临界资源,即必须同步访问,比如无法获得锁的时候,就会被阻塞,直到锁被别的线程释放。当然还有一些阻塞方法:wait() sleep() join()
Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态.
这时候。对某一线程调用 interrupt()时,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。
这是为了打断线程的暂停状态,让线程直接抛出异常,这会使run()方法结束, 并且,在run()方法中抛出,异常不能够跨线程传出到调用线程。
比如join:
一个线程可以在其它线程之上调用join()方法。其效果是等待一段时间直到第二个线程结束才继续执行。如果某个线程在另一个线程上调用 t.join() 此线程将被挂起,直到目标线程t结束才恢复。
可以理解为:加入t的等待集。
public class Sleeper extends Thread{
private int duration;
public Sleeper(String name, int sleepTime){
super(name);
duration = sleepTime;
start();
}
public void run(){
try{
sleep(duration);
}catch(InterruptedException e){
System.out.println(getName() + "was interrupted. ");
return;
}
System.out.println(getName() + " has awakened");
}
}
public class Joiner extends Thread{
private Sleeper sleeper;
public Joiner(String name, Sleeper sleeper){
super(name);
this.sleeper = sleeper;
start();
}
public void run(){
try{
sleeper.join();
}catch(InterruptedException e){
System.out.println("Interrupted");
}
System.out.println(getName() + "join completed");
}
}
public class Joining {
public static void main(String[] args){
Sleeper
sleepy = new Sleeper("Sleepy", 1500),
grumpy = new Sleeper("Grumpy", 1500);
Joiner
dopey = new Joiner("Dopey", sleepy),
doc = new Joiner("Doc", grumpy);
grumpy.interrupt();
}
}
结果:
Grumpywas interrupted.
Docjoin completed
Sleepy has awakened
Dopeyjoin completed
12行结果说明如果被等待的线程结束(被中断或者正常结束),等待它的线程也将结束。
34行结果说明直到等待的线程醒来之后,线程才执行。