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;
}
}
Related
For my current java project, I am trying to generate random ID's for registered users. So far I have been using min +(int) (Math.random()*((max-min)+1)) as my formula to generate the random number. The problem that I am facing is that sometimes the numbers repeat themselves and my application wouldn't work with them.
int min = 1001;
int max = 1050;
for (int i=1; i<=1; i++)
{
int a = min +(int) (Math.random()*((max-min)+1));
}
I have tried using and incorporating
Integer[] arr = new Integer[100];
for (int i = 1; i < arr.length; i++) {
arr[i] = i;
}
Collections.shuffle(Arrays.asList(arr));
but numbers generated would constantly come out as "null" and it would repeat the loop a few hundred times and flood my txt file.
In general, random generators Random or Math.random() are not the correct ways to generate a unique id. As you mentioned, it could be repeated (and it will definitely be).
I would recommend two ways of generating ID.
The first one is to use AtomicInteger. This is good when your ID should be unique but not random.
private static final AtomicInteger ID = new AtomicInteger(0);
public static String generateUniqueId() {
return String.valueOf(ID.incrementAndGet());
}
The second one, which is preferable to me, is to use UUID. This is good when your ID should be as unique as random.
public static String generateUniqueId() {
return String.valueOf(UUID.randomUUID());
}
Another one, I can mention is to use System.nanoTime().
public static String generateUniqueId() {
return String.valueOf(System.nanoTime());
}
Long ago I had some investigation and find out that this is pretty stable for normal payload. But in general, it could retrieve the same value if you build such a system, that should generate ID so often.
Instead of generating numbers I would recommend to generate UUID. The chance of a is collision is close to impossible.
UUID id = UUID.randomUUID();
Otherwise if you want to stick with numbers I would recommend you to implement yourself some Sequence service within your application.
import java.util.concurrent.atomic.AtomicLong;
public class SequenceService {
private final AtomicLong ids;
public SequenceService() {
long initialValue = getInitialValue();
this.ids = new AtomicLong(initialValue);
}
public long generateNextId() {
return ids.incrementAndGet();
}
private long getInitialValue() {
// this methods reads the last known leased id (e.g. from the file system)
}
}
I have a class which loosely implements the HTTP Ranged-GET protocol. Essentially, some code invokes this class, telling it to download a file. The below MyClass is responsible for downloading the file in even-sized chunks (until the last chunk, which may be variable-length), and sending it to another service. When invoked, it sets the file size based on the Content-Range instance-length from the 1st HTTP response.
The class uses an ExecutorService with a thread pool size of 1 to control threading.
Below is the relevant implementation, with some hand-waving over the functions handling the GETs and PUTs.
class MyClass implements Runnable {
private long start;
private long chunkSize;
private int chunkNumber;
private int fileSize = 0;
private static final int MAX_RETRIES = 3;
public static final ExecutorService ES = Executors.newSingleThreadExecutor();
public MyClass(long start, long chunkSize, int chunkNumber) {
this.start = start;
this.chunkSize = chunkSize;
this.chunkNumber = chunkNumber;
}
public void run() {
for (int i = 0; i < MAX_RETRIES; i++) {
long end = start + chunkSize - 1; // inclusive so subtract 1
// doHttpGet() is a private instance function...
// if fileSize == 0 (i.e. first chunk downloaded), this will set the fileSize
doHttpGet(start, end);
// doHttpPost() is a private instance function
// it builds the POST from the GET message, which I'm not bothering to show here
if (!doHttpPost()) {
continue;
} else {
submitNextChunk(this);
break;
}
}
}
// this is the function a client uses to invoke the class
public static void submitWork(long newStartByte, long chunkSize, int chunkNumber) {
MyClass mc = new MyClass(newStartByte, chunkSize, chunkNumber);
if (ES.submit(mc) == null) {
//log error
}
}
// PROBLEM AREA?!?!
private static void submitNextChunk(MyClass mc) {
mc.chunkNumber++;
mc.start += mc.chunkSize;
// LOGGER.debug("start=" + mc.start + "\n" + "fileSize=" + mc.fileSize)
if (mc.start < mc.fileSize) {
if (ES.submit(mc) == null) {
//log error
}
}
}
}
And here is a snippet of the code which invokes MyClass.
long chunkSize = //somecalculation
DownloadAction.submitWork(0L, chunkSize, 1));
This code has been working fine, for a long time. However, I'm now noticing a potentially non-deterministic behavior when the file-to-download is extremely small (e.g., < 50 bytes). What appears to be happening is that the submitNextChunk() function does not seem to evaluate mc.start < mc.fileSize correctly. For example, if we set the packetSize=100K, and use a 50 byte file, then what I see -- via Wireshark -- is continuous HTTP GET requests asking for bytes 0-99999, 100000-199000, and 200000-299000, ..., etc. (The code on the other end is also slightly broken, as it continues to give us the original 50 bytes, rather than an HTTP out-of-range error code... but that another story.)
My concern was that there is a subtle race condition:
If I put some logging in submitNextChunk() to print out start and fileSize, then I only see one log statement of start=100000 and fileSize=100, and the function evaluates the less-than expression correctly to false. This makes sense, since it would be the first and only time submitNextChunk() would be called, and since that expression evaluates false, the function aborts.
I am concerned that this is somehow a threading issue, since without the debug statements, that less-than expression clearly results to true, which should not be occurring.
I'm currently using Hibernate as JPA provider and I want to switch IDs generation from the persistence layer to the application layer.
My schema (on MySQL 5.7) is currently using a BIGINT(20) data-type for IDs, but I don't want to refactor to go for UUIDs.
So I thought that something like a "System" UID should be enough:
public static long getUID()
{
long key = getSystemKey() << 56; // like 0x0100000000000000L;
long ts = System.currentTimeMillis() << 12;
int r = new Random().nextInt(0xFFF);
long id = key + ts + r;
return id;
}
The generated id is in the form
KK TTTTTTTTTTT RRR
where getSystemKey() [K] returns a unique fixed byte for each "machine" the application is running on (it's declared inside the configuration file).
timestamp ts [T] is using 11 nybbles, ensuring enough millis to 2527-06-23 08:20:44.415
random r [R] is used to add randomness per machine per millis (last 3 nybbles).
So I'm wondering if this way is consistent enough, what are pros and cons and if there's a better way.
Thanks
UPDATE
I tested this method with 100 threads and 10,000 executions:
public static void main(String[] args) throws Exception
{
List<Callable<Long>> runners = new ArrayList<>();
for(int i = 0; i < 10000; i++)
{
runners.add(SUID::random);
}
ExecutorService pool = Executors.newFixedThreadPool(100);
List<Future<Long>> results = pool.invokeAll(runners);
pool.shutdown();
int dups = 0;
Set<Long> ids = new HashSet<>();
for(Future<Long> future : results)
{
if(!ids.add(future.get()))
{
dups++;
}
}
System.out.println(dups);
}
I got around 6% of collisions.
So, the only way seems to use some synchronization:
public final class SUID
{
private static final AtomicLong SEQUENCE = new AtomicLong(Config.getSystemKey() << 56 | System.currentTimeMillis() << 12);
private SUID()
{
super();
}
public static long generate()
{
return SEQUENCE.incrementAndGet();
}
}
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. :)
I was surprised that Java's AtomicInteger and AtomicLong classes don't have methods for modular increments (so that the value wraps around to zero after hitting a limit).
I figure I've got to be missing something obvious. What's the best way to do this?
For example, I want to share a simple int between threads, and I want each thread to be able to increment it, say, mod 10.
I can create a class which uses synchronization/locks, but is there a better, easier way?
Just mod 10 the value when you read from it?
public class AtomicWrappingCounter {
private final AtomicLong counter = new AtomicLong();
private final int max;
public AtomicWrappingCounter(int max) {
this.max = max;
}
public int get() {
return (int) (counter.get() % max);
}
public int incrementAndGet() {
return (int) (counter.incrementAndGet() % max);
}
}
Obviously if you might increment this counter more than Long.MAX_VALUE times, you couldn't use this approach, but 9 quintillion is a lot of times to be incrementing (around 292 years at a rate of 1 per nanosecond!).
In Java 8 you can use getAndUpdate (and updateAndGet) in AtomicInteger.
For example if we want to have a counter that wraps to zero each time it hits 10.
AtomicInteger counter = new AtomicInteger(0);
// to get & update
counter.getAndUpdate(value -> (value + 1) % 10)
I would think the simplest way is to build a wrapping counter yourself which stores it's values in an AtomicInteger, something like
public class AtomicWrappingCounter {
private AtomicInteger value;
private final int max;
public AtomicWrappingCounter(int start, int max) {
this.value = new AtomicInteger(start);
this.max = max;
}
public int get() {
return value.get();
}
/* Simple modification of AtomicInteger.incrementAndGet() */
public int incrementAndGet() {
for (;;) {
int current = get();
int next = (current + 1) % max;
if (value.compareAndSet(current, next))
return next;
}
}
}
Why doesn't AtomicInteger provide something like this itself? Who knows, but I think the intention of the concurrency framework authors were to provide some building blocks you could use to better create your own higher-level functions.
What's difficult about adding a synchronized modifier or block to your addModular() method?
The reason why the Atomic classes don't have this functionality is that they're based on specific atomic hardware instructions offered by current CPUs, and modular arithmetic cannot be implemented by those without resorting to locking or other more complex and potentially inefficient algorithms like the one suggested by matt.