I'm trying to implement the Raft Consensus Algorithm for a Distributed System Project, in particular now I'm concentrating about Leader Election Algorithm. Essentially, there are 3 states:
The state passage is pretty complicate if you don't know the algorithm, and I think that the only useful things to know is that each state perform a different task. So I implemented this classes:
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;
}
}
As you can see, in my implementation when you switch from a state to another one, first you (try to) "kill" the task relative to the actual state, and then you submit the task relative to the new state.
I will post a "stupid" implementation of the task performed in the Follower and Candidate states:
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();
}
}
Now, as you can imagine while I execute Follower.run()
the variable future
is referring to the task Follower.run()
. So why if I call SwitchCandidate
during Follower.run()
the InterruptException
thrown by future.cancel(true)
is not catch by Follower.run()
?
In other words, why Follower.run()
doesn't catch the interruption thrown by itself?
Interrupting a Thread
If any thread is in sleeping or waiting state (ie 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.
Example of doing So :
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);}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.