InterruptedException 没有捕获?

InterruptedException not catch?

我正在尝试为分布式系统项目实施 Raft 共识算法,特别是现在我专注于领导者选举算法。本质上,有3种状态:

  1. 追随者
  2. 候选人
  3. 领袖

如果你不知道算法,状态通道会非常复杂,我认为唯一有用的是知道每个状态执行不同的任务。所以我实现了这个 类:

public class ServerStateExecutor {
    private ExecutorService executor;
    private ServerState state;
    private Future<?> future;

    public ServerStateExecutor()
    {
        executor = Executors.newSingleThreadExecutor();
        SwitchFollower();
    }

    public void ExecuteState(ServerState state)
    {
        if(future!=null) {
            future.cancel(true);
        }
        System.out.println("Submitting...");
        future = executor.submit(state);
    }

    public void SwitchFollower() {
        ExecuteState(new Follower(this));
    }

    public void SwitchCandidate() {
        ExecuteState(new Candidate(this));//if true then no Timeout
    }

    public void SwitchLeader() {
        ExecuteState(new Leader(this));
    }
}

public abstract class ServerState implements Runnable {
    protected ServerStateExecutor executor;

    public abstract void run();
    public ServerState(ServerStateExecutor executor)
    {
        this.executor = executor;
    }
}

如您所见,在我的实现中,当您从一种状态切换到另一种状态时,首先您(尝试)"kill" 相对于实际状态的任务,然后提交相对于新状态。

我将post一个"stupid"实现在Follower和Candidate状态下执行的任务:

public class Follower extends ServerState {

    public Follower(ServerStateExecutor executor) {
        super(executor);
    }
    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(10000);
            executor.SwitchCandidate();
        }
        catch(Exception e){System.out.println("INTERRUPTION!");}
    }
}

public class Candidate extends ServerState {

    public Candidate(ServerStateExecutor executor) {
        super(executor);
    }

    @Override
    public void run() {
        try {
            Thread.currentThread().sleep(3000);
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        }
        executor.SwitchFollower();
    }
}

现在,正如您可以想象的那样,当我执行 Follower.run() 时,变量 future 指的是任务 Follower.run()。那么,如果我在 Follower.run() 期间调用 SwitchCandidate,为什么 future.cancel(true) 抛出的 InterruptException 没有被 Follower.run() 捕获?

也就是说,为什么Follower.run()没有捕捉到自己抛出的中断?

中断线程

If any thread is in sleeping or waiting state (i.e. sleep() or wait() is invoked), calling the interrupt() method on the thread, breaks out the sleeping or waiting state throwing InterruptedException. If the thread is not in the sleeping or waiting state, calling the interrupt() method performs normal behaviour and doesn't interrupt the thread but sets the interrupt flag to true.

这样做的例子:

class TestInterruptingThread1 extends Thread{  
public void run(){  
try{  
Thread.sleep(1000);  
System.out.println("task");  
}catch(InterruptedException e){  
throw new RuntimeException("Thread interrupted..."+e);  
}  

}  

public static void main(String args[]){  
TestInterruptingThread1 t1=new TestInterruptingThread1();  
t1.start();  
try{  
t1.interrupt();  
}catch(Exception e){System.out.println("Exception handled "+e);}  

}  
}