Java Fault Tolerant Code Outline

Free Starter Outline code Java, MIT License

package support;

import java.util.function.BiFunction;
import java.util.logging.Logger;

public class FaultToranceUtil {
	private static Logger logger = Logger.getLogger(FaultToranceUtil.class.getName());
	
	public class DisagreementException extends Exception {
		
	}
	
	public static <T,U,R> R tripleModularRedundancy(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not
		
		R valueFromMethod1 = method1.apply(param1, param2);
		R valueFromMethod2 = method2.apply(param1, param2);
		R valueFromMethod3 = method3.apply(param1, param2);
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}		
	}
}

https://en.wikipedia.org/wiki/Triple_modular_redundancy

Currently using sequential processing, makes sense to make this parallel for some cases

Sometimes useful to see how a thought progresses

package support;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.BiFunction;
import java.util.logging.Logger;

import multithreading.ThreadUtil;

public class FaultToranceUtil {
	private static Logger logger = Logger.getLogger(FaultToranceUtil.class.getName());
	
	public static <T,U,R> R tripleModularRedundancySequential(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not
		
		R valueFromMethod1 = method1.apply(param1, param2);
		R valueFromMethod2 = method2.apply(param1, param2);
		R valueFromMethod3 = method3.apply(param1, param2);
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}		
	}
	
	public static <T,U,R> R tripleModularRedundancyParallel(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not
		ConcurrentLinkedQueue<R> values = new ConcurrentLinkedQueue<>();
		
		Runnable task1 = () -> {
			R valueFromMethod1 = method1.apply(param1, param2);
			values.add(valueFromMethod1);
		};
		Runnable task2 = () -> {
			R valueFromMethod2 = method2.apply(param1, param2);
			values.add(valueFromMethod2);
		};
		Runnable task3 = () -> {
			R valueFromMethod3 = method3.apply(param1, param2);
			values.add(valueFromMethod3);
		};
		
		ThreadUtil.addTask(task1);
		ThreadUtil.addTask(task2);
		ThreadUtil.addTask(task3);
		
		boolean waiting=true;
		int timeoutMilliseconds=10000;
		int numberOfIterations=timeoutMilliseconds/50;
		int i=0;
		while (waiting) {
			i++;
			if (values.size()==3 || i>=numberOfIterations) {
				waiting = false;
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				logger.info("Thread interrupted: "+e.getMessage());
			}
		}
		
		if (values.size() == 0 || values.size() == 1) {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}
		
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}		
	}	
}

Free Starter Utility class for Threading in Java, MIT License

package multithreading;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public class ThreadUtil {
	private static Logger logger = Logger.getLogger(ThreadUtil.class.toString());
	private static BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(6);
	private static ThreadPoolExecutor threadPoolExecutor;
	
	
	public static BlockingQueue<Runnable> getWorkQueue() {
		if (null == workQueue) {
			workQueue = new ArrayBlockingQueue<>(6);
		}
		return workQueue;
	}
	
	public static ThreadPoolExecutor getThreadPool() {
		if (null == threadPoolExecutor) {
			threadPoolExecutor = new ThreadPoolExecutor(6, 12, 1000, TimeUnit.MILLISECONDS, getWorkQueue());
		}
		
		return threadPoolExecutor;
	}
	
	public static void addTask(Runnable task) {
		getThreadPool().submit(task);
	}
	
	/* public static void addVirtualTask(Runnable task) {
		getThreadPool().submit(Thread.ofVirtual().start(task));
	} */ // Potential update for Java 19	
}

Barrier in concurrency has potential for loss to ordering of values

package support;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.BiFunction;
import java.util.logging.Logger;

import multithreading.ThreadUtil;

public class FaultToranceUtil {
	private static Logger logger = Logger.getLogger(FaultToranceUtil.class.getName());
	
	public static <T,U,R> R tripleModularRedundancySequential(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not
		
		R valueFromMethod1 = method1.apply(param1, param2);
		R valueFromMethod2 = method2.apply(param1, param2);
		R valueFromMethod3 = method3.apply(param1, param2);
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}		
	}
	
	public static <T,U,R> R tripleModularRedundancyParallel(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not
		ConcurrentLinkedQueue<R> values = new ConcurrentLinkedQueue<>();
		
		Runnable task1 = () -> {
			R valueFromMethod1 = method1.apply(param1, param2);
			values.add(valueFromMethod1);
		};
		Runnable task2 = () -> {
			R valueFromMethod2 = method2.apply(param1, param2);
			values.add(valueFromMethod2);
		};
		Runnable task3 = () -> {
			R valueFromMethod3 = method3.apply(param1, param2);
			values.add(valueFromMethod3);
		};
		
		ThreadUtil.addTask(task1);
		ThreadUtil.addTask(task2);
		ThreadUtil.addTask(task3);
		
		boolean waiting=true;
		int timeoutMilliseconds=10000;
		int numberOfIterations=timeoutMilliseconds/50;
		int i=0;
		while (waiting) {
			i++;
			if (values.size()==3 || i>=numberOfIterations) {
				waiting = false;
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				logger.info("Thread interrupted: "+e.getMessage());
			}
		}
		
		if (values.size() == 0 || values.size() == 1) {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}
		
		R valueFromMethod1, valueFromMethod2, valueFromMethod3;
		if (values.size() == 3) {
			// TODO: Might need a way to match these to which method output them, potential for
			// obfuscated clarity in which one failed
			valueFromMethod1 = values.poll();
			valueFromMethod2 = values.poll();
			valueFromMethod3 = values.poll(); 
		}
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}		
	}	
}

Add this class in the same package

package support;

public class DisagreementException extends Exception {

}

Taking the thought further, ConcurrentHashMap allows values to be mapped

package support;

import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.logging.Logger;

import multithreading.ThreadUtil;

public class FaultToranceUtil {
	private static Logger logger = Logger.getLogger(FaultToranceUtil.class.getName());
	
	public static <T,U,R> R tripleModularRedundancySequential(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not
		
		R valueFromMethod1 = method1.apply(param1, param2);
		R valueFromMethod2 = method2.apply(param1, param2);
		R valueFromMethod3 = method3.apply(param1, param2);
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}		
	}
	
	public static <T,U,R> R tripleModularRedundancyParallel(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not

		ConcurrentHashMap<String, R> values = new ConcurrentHashMap<>();
		
		Runnable task1 = () -> {
			R valueFromMethod1 = method1.apply(param1, param2);
			values.put("method1",valueFromMethod1);
		};
		Runnable task2 = () -> {
			R valueFromMethod2 = method2.apply(param1, param2);
			values.put("method2",valueFromMethod2);
		};
		Runnable task3 = () -> {
			R valueFromMethod3 = method3.apply(param1, param2);
			values.put("method3",valueFromMethod3);
		};
		
		ThreadUtil.addTask(task1);
		ThreadUtil.addTask(task2);
		ThreadUtil.addTask(task3);
		
		boolean waiting=true;
		int timeoutMilliseconds=10000;
		int numberOfIterations=timeoutMilliseconds/50;
		int i=0;
		while (waiting) {
			i++;
			if (values.size()==3 || i>=numberOfIterations) {
				waiting = false;
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				logger.info("Thread interrupted: "+e.getMessage());
			}
		}
		
		if (values.size() == 0 || values.size() == 1) {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}
		
		R valueFromMethod1 = null;
		R valueFromMethod2 = null;
		R valueFromMethod3 = null;
		if (values.size() == 3) {
			// TODO: Might need a way to match these to which method output them, potential for
			// obfuscated clarity in which one failed
			valueFromMethod1 = values.get("method1");
			valueFromMethod2 = values.get("method2");
			valueFromMethod3 = values.get("method3");
		}
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException();
		}		
	}	
}

Updated with better message in Exception

package support;

import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.logging.Logger;

import multithreading.ThreadUtil;

public class FaultToranceUtil {
	private static Logger logger = Logger.getLogger(FaultToranceUtil.class.getName());
	
	public static <T,U,R> R tripleModularRedundancySequential(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not
		
		R valueFromMethod1 = method1.apply(param1, param2);
		R valueFromMethod2 = method2.apply(param1, param2);
		R valueFromMethod3 = method3.apply(param1, param2);
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException("Consensus on value computed can not be made, throwing disagreement exception");
		}		
	}
	
	public static <T,U,R> R tripleModularRedundancyParallel(BiFunction<T, U, R> method1,
			BiFunction<T, U, R> method2,
			BiFunction<T, U, R> method3,
			T param1, U param2) throws DisagreementException {
		// TODO: Create Triple Modular Redundancy class that tries all three methods
		// and gives if two values agree and errors if not

		ConcurrentHashMap<String, R> values = new ConcurrentHashMap<>();
		
		Runnable task1 = () -> {
			R valueFromMethod1 = method1.apply(param1, param2);
			values.put("method1",valueFromMethod1);
		};
		Runnable task2 = () -> {
			R valueFromMethod2 = method2.apply(param1, param2);
			values.put("method2",valueFromMethod2);
		};
		Runnable task3 = () -> {
			R valueFromMethod3 = method3.apply(param1, param2);
			values.put("method3",valueFromMethod3);
		};
		
		ThreadUtil.addTask(task1);
		ThreadUtil.addTask(task2);
		ThreadUtil.addTask(task3);
		
		boolean waiting=true;
		int timeoutMilliseconds=10000;
		int numberOfIterations=timeoutMilliseconds/50;
		int i=0;
		while (waiting) {
			i++;
			if (values.size()==3 || i>=numberOfIterations) {
				waiting = false;
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				logger.info("Thread interrupted: "+e.getMessage());
			}
		}
		
		if (values.size() == 0 || values.size() == 1) {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException("Consensus on value computed can not be made, throwing disagreement exception");
		}
		
		R valueFromMethod1 = null;
		R valueFromMethod2 = null;
		R valueFromMethod3 = null;
		if (values.size() == 3) {
			// TODO: Might need a way to match these to which method output them, potential for
			// obfuscated clarity in which one failed
			valueFromMethod1 = values.get("method1");
			valueFromMethod2 = values.get("method2");
			valueFromMethod3 = values.get("method3");
		}
		
		if (valueFromMethod1==valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			return valueFromMethod1;
		} else if (valueFromMethod1==valueFromMethod2 && valueFromMethod2!=valueFromMethod3) {
			
			logger.info("Alert! Value from method3 is different than method1 and method2");
			return valueFromMethod1;
		} else if (valueFromMethod1!=valueFromMethod2 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method1 is different than method2 and method3");
			return valueFromMethod2;
		} else if (valueFromMethod1==valueFromMethod3 && valueFromMethod2==valueFromMethod3) {
			
			logger.info("Alert! Value from method2 is different than method1 and method3");
			return valueFromMethod1;
		} else {
			logger.severe("Consensus on value computed can not be made, throwing disagreement exception");
			throw new DisagreementException("Consensus on value computed can not be made, throwing disagreement exception");
		}		
	}	
}
package support;

public class DisagreementException extends Exception {

	public DisagreementException(final String message) {
		super(message);
	}
}

Triple Modular Redundant Encouragement

Published by techinfodebug

Flex and Java Developer, Christian, Art, Music, Video, and Vlogging

Leave a comment