Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 131743
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T06:09:12+00:00 2026-05-11T06:09:12+00:00

I recently refactored a piece of code used to generate unique negative numbers. edit:

  • 0

I recently refactored a piece of code used to generate unique negative numbers.
edit: Multiple threads obtain these ids and add as keys to a DB; numbers need to be negative to be easily identifiable -at the end of a test session they’re removed from the DB.

My Java algorithm looks like this:

private final Set<Integer> seen = Collections.synchronizedSet(new HashSet<Integer>()); public Integer generateUniqueNegativeIds() {     int result = 0;     do {         result = random.nextInt();         if (result > 0) {             result *= -1;         }     } while (!seen.add(result));     return result; } 

The code structure above, with its speculative addition to the set and ‘retry’ loop, makes me think there’s an equivalent nonblocking algorithm that replaces the synchronized set with any of the atomic variables.

I made a few attempts to re-write using atomic variables but all failed the multithread attack test.

Is there an elegant nonblocking equivalent?

edit: for curiosity’s sake here’s a flawed attempt using an atomic integer as a guard

private final AtomicInteger atomi = new AtomicInteger(0); public Integer generateUniqueNegativeIdsWithAtomicAlgo() {     boolean added = false;     int result = 0;     do {         result = random.nextInt();         if (result > 0) {             result *= -1;         }         if (atomi.compareAndSet(0, result)) {             added = cache.add(result);         }        } while (!added);     return atomi.getAndSet(0); } 

edit: test harness below:

public static void main(String[] args) {     final int NUMBER_OF_THREADS = 10000;     final Set<Integer> uniques = Collections.synchronizedSet(new HashSet<Integer>());     final List<Integer> positives = Collections.synchronizedList(new ArrayList<Integer>());     final NegativeUniqueIdGenerator nuig = new NegativeUniqueIdGenerator();     Thread[] workers = new Thread[NUMBER_OF_THREADS];     long start = System.nanoTime();     for (int i = 0; i < workers.length; i++) {         Runnable runnable = new Runnable() {             public void run() {                 int number = nuig.generateUniqueNegativeIds();                 if (number > 0) {                     positives.add(number);                 }                 uniques.add(number);             }         };         workers[i] = new Thread(runnable);         workers[i].start();     }     for (int i = 0; i < workers.length; i++) {         try {             workers[i].join();         } catch (InterruptedException ie) {}     }     long end = System.nanoTime();     System.out.println(String.format('duration = %dns', (end - start)));     System.out.println(String.format('#threads = %d', NUMBER_OF_THREADS));     System.out.println(String.format('#uniques = %d', uniques.size()));     System.out.println(String.format('#positives = %d', positives.size()));     System.out.println(String.format('#duplicates = %d', NUMBER_OF_THREADS - uniques.size()));     System.out.println(String.format('ratio = %f',             ((double) NUMBER_OF_THREADS - uniques.size())                     / NUMBER_OF_THREADS));     assert uniques.size() == NUMBER_OF_THREADS; } 
  • 1 1 Answer
  • 4 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-11T06:09:13+00:00Added an answer on May 11, 2026 at 6:09 am

    From the requirements you’ve given, I would personally just use a medium-quality random number generator that you know won’t produce duplicates within the number of unique numbers that you require. Unless you have an extra requirement you haven’t mentioned, it seems overkill to keep the set of all the previously generated numbers.

    For example, using a 32-bit XORShift generator will produce all 2^31 negative 4-byte integers in ‘random’ order before repeating the pattern. If you need more numbers than that, you probably don’t want to be putting them in a hash set anyway. So something like this (warning: off-top-of-head untested code…):

    int seed = (int) System.nanoTime(); final int origSeed = seed;  public int nextUniqueNegativeNumber() {   int n = seed;   do {     n ^= (n << 13);     n ^= (n >>> 17);     n ^= (n << 5);     seed = n;     if (n == origSeed) {       throw new InternalError('Run out of numbers!');     }   } while (n > 0);   return n; } 

    I’ll leave it up to the reader to convert ‘seed’ to use an AtomicInteger if concurrency is necessary…

    Edit: actually, to optimise the concurrent case you maybe only want to write back to ‘seed’ after getting the next negative number.

    OK, by popular demand, the atomic version would then be something like this:

      AtomicInteger seed = new AtomicInteger((int) System.nanoTime());    public int nextUniqueNegativeNumber() {     int oldVal, n;     do {       do {         oldVal = seed.get();         n = oldVal ^ (oldVal << 13); // Added correction         n ^= (n >>> 17);         n ^= (n << 5);       } while (seed.getAndSet(n) != oldVal);     } while (n > 0);     return n;   } 
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I recently refactored some of my code to stuff rows into a db using
I recently refactored some code in an Active Directory role provider to remove support
I recently refactored code like this ( MyClass to MyClassR ). #include <iostream> class
I recently refactored old code files from ABCFile.cpp/.h to AbcFile.cpp/.h to match my company's
I have a DataTrigger that I recently refactored. It used to have the DataContext
I recently refactored some code, and a method the original Global.asax.cs file was depending
Recently a friend and I were talking about securing stored procedure code in a
I've recently refactored an existing CodeIgniter application to use url segments instead of query
I've recently refactored my application with the following: Linq to SQL db connection Objects
I recently read Michael C. Feathers' book Working effectively with legacy code and came

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.