We have a business requirement to generate random temporary passwords. As per the use case, the volume of such calls is expected to be very low (~400 calls/day). We've decided to use java.security.SecureRandom to achieve cryptographically strong randomization, as per various recommendations on the Internet, and after reading many similar posts on SO.
Now, we've written a simple randomizer (internally using the SecureRandom), which is supposed to be used as a singleton within the web application. However, we would also periodically want to reseed it, again as per recommendations on SO. To that end, below is some sample code that achieves the same. Can someone please review it and let us know if this is the right and reasonably efficient approach? Also, is there a way to avoid the synchronization in the code, while still maintaining thread safety?:
import java.security.*;
public final class Randomizer {
private static final Randomizer INSTANCE = new Randomizer();
private static final String DEFAULT_CSPRNG_ALGO = "SHA1PRNG";
private volatile SecureRandom sr;
private volatile long lastSeedTime;
public static final Randomizer getInstance() throws Exception {
return INSTANCE;
}
public int nextInt(int len) throws RuntimeException {
reseedRandomAsNeeded();
return sr.nextInt(len);
}
private Randomizer() throws RuntimeException {
try {
System.out.printf("%s Constructing Randomizer...%n", Thread.currentThread());
recreateSecureRandomInstance();
lastSeedTime = System.nanoTime();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
/**
* TODO Is there a way to avoid the synchronization overhead here? We really
* only need to synchronize when the reseed happens.
*
* #throws RuntimeException
*/
private synchronized void reseedRandomAsNeeded() throws RuntimeException {
if (isItTimeToReseed()) {
// TODO Need to do a reseed. Just get a new SecureRandom for now.
try {
recreateSecureRandomInstance();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
private boolean isItTimeToReseed() {
boolean reseed = false;
long currentTime = System.nanoTime();
long difference = ((currentTime - this.lastSeedTime) / (1000 * 1000 * 1000)/* *60 * 60 * 24*/);
// System.out.printf("%s Current time: %d, Last Reseed Time: %d, difference: %d%n",
// Thread.currentThread(), currentTime, lastSeedTime, difference);
// TODO For testing, test for just a 3 seconds difference.
if (difference > 3) {
reseed = true;
this.lastSeedTime = currentTime;
}
return reseed;
}
private void recreateSecureRandomInstance() throws NoSuchAlgorithmException {
sr = SecureRandom.getInstance(DEFAULT_CSPRNG_ALGO);
System.out.printf("%s Created a new SecureRandom instance: %s%n", Thread.currentThread(), sr);
}
}
Instead of time based, you can reseed based on number of invocations.
Maintain a counter in the class and increase it every time the random generator is called. When the counter reaches some threshold, reseed it and initialize count to to 0.
You can reseed say for every 1 million invocations.
That is the only thing I can suggest.
Related
I'm new to multithreading in general, so I still don't fully understand it. I don't get why my code is having issues. I'm trying to populate an ArrayList with the first 1000 numbers, and then sum all of them using three threads.
public class Tst extends Thread {
private static int sum = 0;
private final int MOD = 3;
private final int compare;
private static final int LIMIT = 1000;
private static ArrayList<Integer> list = new ArrayList<Integer>();
public Tst(int compare){
this.compare=compare;
}
public synchronized void populate() throws InterruptedException{
for(int i=0; i<=Tst.LIMIT; i++){
if (i%this.MOD == this.compare){
list.add(i);
}
}
}
public synchronized void sum() throws InterruptedException{
for (Integer ger : list){
if (ger%MOD == this.compare){
sum+=ger;
}
}
}
#Override
public void run(){
try {
populate();
sum();
System.out.println(sum);
} catch (InterruptedException ex) {
Logger.getLogger(Tst.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
Tst tst1 = new Tst(0);
tst1.start();
Tst tst2 = new Tst(1);
tst2.start();
Tst tst3 = new Tst(2);
tst3.start();
}
}
I expected it to print "500.500", but instead it prints this:
162241
328741
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
at tst.Tst.sum(Tst.java:38)
at tst.Tst.run(Tst.java:50)
BUILD SUCCESSFUL (total time: 2 seconds)
The problem is happening because your methods are synchronized in "object level", I mean, the monitor lock it uses is of a particular object (tst1,tst2,tst3). In other words, each synchronized method is using a different lock.
Change your synchronized methods to static as a first step to fix it.
while run of tst1 is counting the sum in for-each then run of tst2 might increasing the size of list. So its throwing concurrent modification exception. Using a join can help.
public static void main(String[] args) {
Tst tst1 = new Tst(0);
tst1.start();
tst1.join()
Tst tst2 = new Tst(1);
tst2.start();
tst1.join()
Tst tst3 = new Tst(2);
tst3.start();
}
You misunderstood the semantic of synchronized method, each one uses different lock object in your case, do it this way:
class SynchList {
private int sum = 0;
private final int MOD = 3;
private int compare;
private final int LIMIT = 1000;
private ArrayList<Integer> list = new ArrayList<Integer>();
public synchronized void populate( int compare) throws InterruptedException{
for(int i=0; i<=LIMIT; i++){
if (i%this.MOD == compare){
list.add(i);
}
}
}
public synchronized void sum( int compare ) throws InterruptedException{
for (Integer ger : list){
if (ger%MOD == compare){
sum+=ger;
}
System.out.println( sum );
}
}
}
class Tst extends Thread {
int compare;
SynchList synchList;
public Tst(int compare, SynchList synchList)
{
this.compare= compare;
this.synchList = synchList;
}
#Override
public void run(){
try {
synchList.populate( compare );
synchList.sum( compare );
} catch (InterruptedException ex) {
Logger.getLogger(Tst.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class Main
{
public static void main(String[] args) {
SynchList synchList = new SynchList();
Tst tst1 = new Tst( 0 , synchList );
tst1.start();
Tst tst2 = new Tst( 1, synchList );
tst2.start();
Tst tst3 = new Tst( 2, synchList );
tst3.start();
}
}
Your use of synchronized methods isn't doing what you think it's doing. The way your code is written, the methods "sum" and "populate" are protected
from running at the same time, but only on the same thread instance. That means calls to "sum" and "populate" for a single Tst object will happen one at a time,
but simultaneous calls to "sum" on different object instances will be allowed to happen concurrently.
Using synchronized on a method is equivalent to writing a method that is wrapped
with synchronized(this) { ... } around the entire method body. With three different instances created – tst1, tst2, and tst3 – this form of synchronization
doesn't guard across object instances. Instead, it guarantees that only one of populate or sum will be running at a time on a single object; any other calls to one of
those methods (on the same object instance) will wait until the prior one finishes.
Take a look at 8.4.3.6. synchronized Methods in the Java Language Specification
for more detail.
Your use of static might also not be doing what you think it's doing. Your code also shares things across all instances of the Tst thread class – namely, sum and list. Because these are defined as static,
there will be a one sum and one list. There is no thread safety in your code to guard against concurrent changes to either of those.
For example, as threads are updating
"sum" (with the line: sum+=ger), the results will be non-deterministic. That is, you will likely see different results every time you run it.
Another example of unexpected behavior with multiple threads and a single static variable is list – that will grow over time which can result in concurrency issues. The Javadoc says:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
Modifications include adding values as well as growing the backing array store. Without specifying a starting size – new ArrayList() – it will default to 10 or possibly some other relatively small number depending on which JVM version you're using. Once one thread tries to add an item that exceeds the ArrayList's capacity, it will trigger an automatic resize.
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
I want to perform a search using iterative deepening, meaning every time I do it, I go deeper and it takes longer. There is a time limit (2 seconds) to get the best result possible. From what I've researched, the best way to do this is using an ExecutorService, a Future and interrupting it when the time runs out. This is what I have at the moment:
In my main function:
ExecutorService service = Executors.newSingleThreadExecutor();
ab = new AB();
Future<Integer> f = service.submit(ab);
Integer x = 0;
try {
x = f.get(1990, TimeUnit.MILLISECONDS);
}
catch(TimeoutException e) {
System.out.println("cancelling future");
f.cancel(true);
}
catch(Exception e) {
throw new RuntimeException(e);
}
finally {
service.shutdown();
}
System.out.println(x);
And the Callable:
public class AB implements Callable<Integer> {
public AB() {}
public Integer call() throws Exception {
Integer x = 0;
int i = 0;
while (!Thread.interrupted()) {
x = doLongComputation(i);
i++;
}
return x;
}
}
I have two problems:
doLongComputation() isn't being interrupted, the program only checks if Thread.interrupted() is true after it completes the work. Do I need to put checks in doLongComputation() to see if the thread has been interrupted?
Even if I get rid of the doLongComputation(), the main method isn't receiving the value of x. How can I ensure that my program waits for the Callable to "clean up" and return the best x so far?
To answer part 1: Yes, you need to have your long task check the interrupted flag. Interruption requires the cooperation of the task being interrupted.
Also you should use Thread.currentThread().isInterrupted() unless you specifically want to clear the interrupt flag. Code that throws (or rethrows) InterruptedException uses Thread#interrupted as a convenient way to both check the flag and clear it, when you're writing a Runnable or Callable this is usually not what you want.
Now to answer part 2: Cancellation isn't what you want here.
Using cancellation to stop the computation and return an intermediate result doesn't work, once you cancel the future you can't retrieve the return value from the get method. What you could do is make each refinement of the computation its own task, so that you submit one task, get the result, then submit the next using the result as a starting point, saving the latest result as you go.
Here's an example I came up with to demonstrate this, calculating successive approximations of a square root using Newton's method. Each iteration is a separate task which gets submitted (using the previous task's approximation) when the previous task completes:
import java.util.concurrent.*;
import java.math.*;
public class IterativeCalculation {
static class SqrtResult {
public final BigDecimal value;
public final Future<SqrtResult> next;
public SqrtResult(BigDecimal value, Future<SqrtResult> next) {
this.value = value;
this.next = next;
}
}
static class SqrtIteration implements Callable<SqrtResult> {
private final BigDecimal x;
private final BigDecimal guess;
private final ExecutorService xs;
public SqrtIteration(BigDecimal x, BigDecimal guess, ExecutorService xs) {
this.x = x;
this.guess = guess;
this.xs = xs;
}
public SqrtResult call() {
BigDecimal nextGuess = guess.subtract(guess.pow(2).subtract(x).divide(new BigDecimal(2).multiply(guess), RoundingMode.HALF_EVEN));
return new SqrtResult(nextGuess, xs.submit(new SqrtIteration(x, nextGuess, xs)));
}
}
public static void main(String[] args) throws Exception {
long timeLimit = 10000L;
ExecutorService xs = Executors.newSingleThreadExecutor();
try {
long startTime = System.currentTimeMillis();
Future<SqrtResult> f = xs.submit(new SqrtIteration(new BigDecimal("612.00"), new BigDecimal("10.00"), xs));
for (int i = 0; System.currentTimeMillis() - startTime < timeLimit; i++) {
f = f.get().next;
System.out.println("iteration=" + i + ", value=" + f.get().value);
}
f.cancel(true);
} finally {
xs.shutdown();
}
}
}
I would like to be able to run two methods at the same time that rely on the same global variable. The first method periodically updates the shared variable, but never finishes running. The second method keeps track of time. When time runs out, the second method returns the last result of the shared variable from the first method. Below is what I have so far, with commented out pseduocode in the places where I need help.
package learning;
public class testmath{
public static void main(String[] args){
long finishBy = 10000;
int currentresult = 0;
/*
* run eversquare(0) in a seperate thread /in parallel
*/
int finalresult = manager(finishBy);
System.out.println(finalresult);
}
public static int square(int x){
return x * x;
}
public static void eversquare(int x){
int newresult;
while(2 == 2){
x += 1;
newresult = square(x);
/*
* Store newresult as a global called currentresult
*/
}
}
public static int manager(long finishBy){
while(System.currentTimeMillis() + 1000 < finishBy){
Thread.sleep(100);
}
/*
* Access global called currentresult and create a local called currentresult
*/
return currentresult;
}
}
You only need to run one additional thread:
public class Main {
/**
* Delay in milliseconds until finished.
*/
private static final long FINISH_BY = 10000;
/**
* Start with this number.
*/
private static final int START_WITH = 1;
/**
* Delay between eversquare passes in milliseconds.
*/
private static final long DELAY_BETWEEN_PASSES = 50;
/**
* Holds the current result. The "volatile" keyword tells the JVM that the
* value could be changed by another thread, so don't cache it. Marking a
* variable as volatile incurs a *serious* performance hit so don't use it
* unless really necessary.
*/
private static volatile int currentResult = 0;
public static void main(String[] args) {
// create a Thread to run "eversquare" in parallel
Thread eversquareThread = new Thread(new Runnable() {
#Override public void run() {
eversquare(START_WITH, DELAY_BETWEEN_PASSES);
}
});
// make the eversquare thread shut down when the "main" method exits
// (otherwise the program would never finish, since the "eversquare" thread
// would run forever due to its "while" loop)
eversquareThread.setDaemon(true);
// start the eversquare thread
eversquareThread.start();
// wait until the specified delay is up
long currentTime = System.currentTimeMillis();
final long stopTime = currentTime + FINISH_BY;
while (currentTime < stopTime) {
final long sleepTime = stopTime - currentTime;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException ex) {
// in the unlikely event of an InterruptedException, do nothing since
// the "while" loop will continue until done anyway
}
currentTime = System.currentTimeMillis();
}
System.out.println(currentResult);
}
/**
* Increment the value and compute its square. Runs forever if left to its own
* devices.
*
* #param startValue
* The value to start with.
*
* #param delay
* If you were to try to run this without any delay between passes, it would
* max out the CPU and starve any other threads. This value is the wait time
* between passes.
*/
private static void eversquare(final int startValue, final long delay) {
int currentValue = startValue;
while (true) { // run forever (just use "true"; "2==2" looks silly)
currentResult = square(currentValue); // store in the global "currentResult"
currentValue++; // even shorter than "x += 1"
if (delay > 0) {
try { // need to handle the exception that "Thread.sleep()" can throw
Thread.sleep(delay);
} catch (InterruptedException ex) { // "Thread.sleep()" can throw this
// just print to the console in the unlikely event of an
// InterruptedException--things will continue fine
ex.printStackTrace();
}
}
}
}
private static int square(int x) {
return x * x;
}
}
I should also mention that the "volatile" keyword works for (most) primitives, since any JVM you'll see these days guarantees they will be modified atomically. This is not the case for objects, and you will need to use synchronized blocks and locks to ensure they are always "seen" in a consistent state.
Most people will also mention that you really should not use the synchronized keyword on the method itself, and instead synchronize on a specific "lock" object. And generally this lock object should not be visible outside your code. This helps prevent people from using your code incorrectly, getting themselves into trouble, and then trying to blame you. :)
After taking help from StackOverflow, I found the solution that I have implemented below.
Problem Statement:-
Each thread needs to use UNIQUE ID every time and it has to run for 60 minutes or more, So in that 60 minutes it is possible that all the ID's will get finished so I need to reuse those ID's again. So I am using ArrayBlockingQueue concept here.
Two Scenario:-
If the command.getDataCriteria() contains Previous then each thread
always needs to use UNIQUE ID between 1 and 1000 and release it for reusing
again.
Else if the command.getDataCriteria() contains New then each thread
always needs to use UNIQUE ID between 2000 and 3000 and release it for
reusing again.
Question:-
One weird thing that I have just noticed is- In the below else if loop if you see my below code in run method if the command.getDataCriteria() is Previous then also it gets entered in the else if block(which is for New) which shouldn't be happening right as I am doing a .equals check? Why this is happening?
else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) {
Below is my code:-
class ThreadNewTask implements Runnable {
private Command command;
private BlockingQueue<Integer> existPool;
private BlockingQueue<Integer> newPool;
private int existId;
private int newId;
public ThreadNewTask(Command command, BlockingQueue<Integer> pool1, BlockingQueue<Integer> pool2) {
this.command = command;
this.existPool = pool1;
this.newPool = pool2;
}
public void run() {
if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_PREVIOUS)) {
try {
existId = existPool.take();
someMethod(existId);
} catch (Exception e) {
System.out.println(e);
} finally {
existPool.offer(existId);
}
} else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) {
try {
newId = newPool.take();
someMethod(newId);
} catch (Exception e) {
System.out.println(e);
} finally {
newPool.offer(newId);
}
}
}
// And this method needs to be synchronized or not?
private synchronized void someMethod(int i) {
System.out.println();
System.out.println("#####################");
System.out.println("Task ID: " +i);
System.out.println("#####################");
System.out.println();
}
}
public class TestingPool {
public static void main(String[] args) throws InterruptedException {
int size = 10;
int durationOfRun = 60;
LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
LinkedList<Integer> availableNewIds = new LinkedList<Integer>();
for (int i = 1; i <= 1000; i++) {
availableExistingIds.add(i);
}
for (int i = 2000; i <= 3000; i++) {
availableNewIds.add(i);
}
BlockingQueue<Integer> existIdPool = new ArrayBlockingQueue<Integer>(1000, false, availableExistingIds);
BlockingQueue<Integer> newIdPool = new ArrayBlockingQueue<Integer>(1000, false, availableNewIds);
// create thread pool with given size
ExecutorService service = new ThreadPoolExecutor(size, size, 500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
// queue some tasks
long startTime = System.currentTimeMillis();
long endTime = startTime + (durationOfRun * 60 * 1000L);
// Running it for 60 minutes
while(System.currentTimeMillis() <= endTime) {
Command nextCommand = getNextCommandToExecute();
service.submit(new ThreadNewTask(nextCommand, existIdPool, newIdPool));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
Update:-
One weird thing that I have just noticed is- In the below else if loop if the command is Previous then also it gets entered in the else if block which shouldn't be happening right? Why this is happening? I have no clue why this thing is happening?
else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) {
There is no way if you enter an if () that you enter the else as well so something else is happening. I don't see anything wrong with your code so I suspect that you are misinterpreting your output. Are you expecting a different Command to come from getNextCommandToExecute()?
I just ran your code with a simulated Command which sets a random dataCriteria and got the following output. I see nothing wrong with it:
Task ID: 2001
Task ID: 1
Task ID: 2002
Task ID: 2003
Task ID: 2
Task ID: 2004
Task ID: 3
Task ID: 2005
...
Are you expecting some sort of specific timing for your threads? Given thread race conditions, the first Command produced is not necessarily the first output you will see.
Here is some general feedback on your code:
I would use pool.put(...) instead of offer(...) which could return false.
You might as well fill your queues after you construct them as opposed to loading them with a LinkedList.
You should use ArrayList instead of LinkedList usually.
You load in for (int i = 2000; i <= 3000; i++) but that needs to be from 2001 to 3000 else it will be more than 1000 numbers.
I need to generate monotonically increasing integers.
Could I use the timestamp to somehow generate such type of integer sequence?
I would request an integer at a time, and I won't be requesting more than an integer in the same second's interval - if I do, I won't mind if it passes me the same integer within that second's interval.
You can use an AtomicInteger object to maintain a thread safe counter. Then use getAndIncrement() when you need the next integer.
Since monotonically increasing integers do not need to be contiguous (ie there can be gaps, as long as the number keeps increasing), and it sounds like you want all calls made in the same second to return the same integer, a method that returns how many seconds the JVM has been up would do nicely.
Here's a simple implementation that does that:
private static long startTime = System.currentTimeMillis();
public static int secondsSinceStart() {
return (int) TimeUnit.SECONDS.convert(
System.currentTimeMillis() - startTime, TimeUnit.MILLISECONDS);
}
FYI, this would last 68 years before rolling over.
This is my self made generator...
public final class IdGenerator {
private static final int MAGNITUDE = 10000;
private static long previousTimestamp;
private static int counter = 0;
private IdGenerator() {
}
public synchronized static long generateId() {
final long timeMillis = System.currentTimeMillis();
if (previousTimestamp != timeMillis) {
counter = 0;
}
previousTimestamp = timeMillis;
final int counterValue = counter++;
if (counterValue >= MAGNITUDE) {
//just to be sure
throw new IllegalStateException("too many id generated for a single timestamp!");
}
return timeMillis * MAGNITUDE + counterValue;
}
}