java.util.concurrent.atomic.AtomicLong#get()源码实例Demo

下面列出了java.util.concurrent.atomic.AtomicLong#get() 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: antsdb   文件: FishUtf8.java
public static long allocSet(Heap heap, String string) {
    if (string == null) {
        return 0;
    }
    int size = string.length() * 3;
    long pResult = heap.alloc(HEADER_SIZE + size, false);;
    AtomicLong pData = new AtomicLong(pResult + HEADER_SIZE);
    Unsafe.putByte(pResult, Value.FORMAT_UTF8);
    Utf8.encode(string, n -> {
        Unsafe.putByte(pData.getAndIncrement(), (byte)n);
    });
    long realSize = pData.get() - pResult - HEADER_SIZE;
    if (realSize > 0xffffff) {
        throw new IllegalArgumentException();
    }
    Unsafe.putInt3(pResult + 1, (int)realSize);
    return pResult;
}
 
源代码2 项目: smallrye-mutiny   文件: Subscriptions.java
/**
 * Atomically adds the positive value n to the requested value in the {@link AtomicLong} and
 * caps the result at {@link Long#MAX_VALUE} and returns the previous value and
 * considers {@link Long#MIN_VALUE} as a cancel indication (no addition then).
 *
 * @param requested the {@code AtomicLong} holding the current requested value
 * @param n the value to add, must be positive (not verified)
 * @return the original value before the add
 */
public static long addAndHandledAlreadyCancelled(AtomicLong requested, long n) {
    for (;;) {
        long r = requested.get();
        if (r == Long.MIN_VALUE) {
            return Long.MIN_VALUE;
        }
        if (r == Long.MAX_VALUE) {
            return Long.MAX_VALUE;
        }
        long u = add(r, n);
        if (requested.compareAndSet(r, u)) {
            return r;
        }
    }
}
 
源代码3 项目: gemfirexd-oss   文件: IdentityValueManager.java
/**
 * Get the generated IDENTITY value for given table next to the one last
 * retrieved by this node. Also mark the value to have been read by the new
 * generating node that is reading this IDENTITY value.
 */
public long getAfterRetrievedValue(Object table, long start, long increment,
    DistributedMember idGeneratingNode) {
  this.generatedValuesLock.attemptWriteLock(-1);
  try {
    Object[] id = this.generatedValues.get(table);
    if (id != null) {
      AtomicLong currValue = (AtomicLong)id[0];
      id[1] = idGeneratingNode;
      return (currValue.get() + increment);
    }
    else {
      this.generatedValues.put(table, new Object[] { new AtomicLong(start),
          idGeneratingNode });
      return start;
    }
  } finally {
    this.generatedValuesLock.releaseWriteLock();
  }
}
 
源代码4 项目: antsdb   文件: AtomicUtil.java
public static boolean max(AtomicLong x, long y) {
	for (;;) {
		long value = x.get();
		if (y > value) {
			if (!x.compareAndSet(value, y)) {
				continue;
			}
			return true;
		}
		else {
			return false;
		}
	}
}
 
源代码5 项目: codebuff   文件: AtomicLongMap.java
/**
 * Removes all mappings from this map whose values are zero.
 *
 * <p>This method is not atomic: the map may be visible in intermediate states, where some of the
 * zero values have been removed and others have not.
 */


public void removeAllZeros() {
  Iterator<Map.Entry<K, AtomicLong>> entryIterator = map.entrySet().iterator();
  while (entryIterator.hasNext()) {
    Map.Entry<K, AtomicLong> entry = entryIterator.next();
    AtomicLong atomic = entry.getValue();
    if (atomic != null && atomic.get() == 0L) {
      entryIterator.remove();
    }
  }
}
 
源代码6 项目: rocketmq   文件: PullAPIWrapper.java
public long recalculatePullFromWhichNode(final MessageQueue mq) {
    if (this.isConnectBrokerByUser()) {
        return this.defaultBrokerId;
    }

    AtomicLong suggest = this.pullFromWhichNodeTable.get(mq);
    if (suggest != null) {
        return suggest.get();
    }

    return MixAll.MASTER_ID;
}
 
源代码7 项目: openjdk-8-source   文件: Test7009231.java
protected void clearBit(AtomicLong atomic, long lMask) {
    long lWord;
    do {
        lWord = atomic.get();
    } while (!atomic.compareAndSet(lWord, lWord & ~lMask));

    if ((atomic.get() & lMask) != 0L) {
        throw new InternalError();
    }
}
 
源代码8 项目: openjdk-jdk9   文件: LongAdderDemo.java
public void run() {
    phaser.arriveAndAwaitAdvance();
    phaser.arriveAndAwaitAdvance();
    AtomicLong a = adder;
    for (int i = 0; i < incs; ++i)
        a.getAndIncrement();
    result = a.get();
    phaser.arrive();
}
 
源代码9 项目: openjdk-jdk8u-backup   文件: ForkJoinPool.java
/**
 * Returns an estimate of the total number of tasks stolen from
 * one thread's work queue by another. The reported value
 * underestimates the actual total number of steals when the pool
 * is not quiescent. This value may be useful for monitoring and
 * tuning fork/join programs: in general, steal counts should be
 * high enough to keep threads busy, but low enough to avoid
 * overhead and contention across threads.
 *
 * @return the number of steals
 */
public long getStealCount() {
    AtomicLong sc = stealCounter;
    long count = (sc == null) ? 0L : sc.get();
    WorkQueue[] ws; WorkQueue w;
    if ((ws = workQueues) != null) {
        for (int i = 1; i < ws.length; i += 2) {
            if ((w = ws[i]) != null)
                count += w.nsteals;
        }
    }
    return count;
}
 
源代码10 项目: codebuff   文件: AtomicLongMap.java
/**
 * Adds {@code delta} to the value currently associated with {@code key}, and returns the new
 * value.
 */

@CanIgnoreReturnValue
public long addAndGet(K key, long delta) {
  outer:
  while (true) {
    AtomicLong atomic = map.get(key);
    if (atomic == null) {
      atomic = map.putIfAbsent(key, new AtomicLong(delta));
      if (atomic == null) {
        return delta;
      }
      // atomic is now non-null; fall through
    }

    while (true) {
      long oldValue = atomic.get();
      if (oldValue == 0L) {
        // don't compareAndSet a zero
        if (map.replace(key, atomic, new AtomicLong(delta))) {
          return delta;
        }
        // atomic replaced
        continue outer;
      }
      long newValue = oldValue + delta;
      if (atomic.compareAndSet(oldValue, newValue)) {
        return newValue;
      }
      // value changed
    }
  }
}
 
源代码11 项目: codebuff   文件: AtomicLongMap.java
/**
 * Associates {@code newValue} with {@code key} in this map, and returns the value previously
 * associated with {@code key}, or zero if there was no such value.
 */
@CanIgnoreReturnValue
public long put(K key, long newValue) {
  outer:
  while (true) {
    AtomicLong atomic = map.get(key);
    if (atomic == null) {
      atomic = map.putIfAbsent(key, new AtomicLong(newValue));
      if (atomic == null) {
        return 0L;
      }
      // atomic is now non-null; fall through
    }

    while (true) {
      long oldValue = atomic.get();
      if (oldValue == 0L) {
        // don't compareAndSet a zero
        if (map.replace(key, atomic, new AtomicLong(newValue))) {
          return 0L;
        }
        // atomic replaced
        continue outer;
      }

      if (atomic.compareAndSet(oldValue, newValue)) {
        return oldValue;
      }
      // value changed
    }
  }
}
 
源代码12 项目: rocketmq   文件: PullAPIWrapper.java
public long recalculatePullFromWhichNode(final MessageQueue mq) {
    if (this.isConnectBrokerByUser()) {
        return this.defaultBrokerId;
    }

    AtomicLong suggest = this.pullFromWhichNodeTable.get(mq);
    if (suggest != null) {
        return suggest.get();
    }

    return MixAll.MASTER_ID;
}
 
源代码13 项目: deeplearning4j   文件: CBOW.java
public Sequence<T> applySubsampling(@NonNull Sequence<T> sequence, @NonNull AtomicLong nextRandom) {
    Sequence<T> result = new Sequence<>();

    // subsampling implementation, if subsampling threshold met, just continue to next element
    if (sampling > 0) {
        result.setSequenceId(sequence.getSequenceId());
        if (sequence.getSequenceLabels() != null)
            result.setSequenceLabels(sequence.getSequenceLabels());
        if (sequence.getSequenceLabel() != null)
            result.setSequenceLabel(sequence.getSequenceLabel());

        for (T element : sequence.getElements()) {
            double numWords = vocabCache.totalWordOccurrences();
            double ran = (Math.sqrt(element.getElementFrequency() / (sampling * numWords)) + 1)
                            * (sampling * numWords) / element.getElementFrequency();

            nextRandom.set(Math.abs(nextRandom.get() * 25214903917L + 11));

            if (ran < (nextRandom.get() & 0xFFFF) / (double) 65536) {
                continue;
            }
            result.addElement(element);
        }
        return result;
    } else
        return sequence;
}
 
源代码14 项目: deeplearning4j   文件: CBOW.java
public void iterateSample(T currentWord, int[] windowWords, boolean[] wordStatuses, AtomicLong nextRandom, double alpha,
                          boolean isInference, int numLabels, boolean trainWords, INDArray inferenceVector) {
    int[] idxSyn1 = null;
    byte[] codes = null;

    if (configuration.isUseHierarchicSoftmax()) {
        idxSyn1 = new int[currentWord.getCodeLength()];
        codes = new byte[currentWord.getCodeLength()];
        for (int p = 0; p < currentWord.getCodeLength(); p++) {
            if (currentWord.getPoints().get(p) < 0)
                continue;

            codes[p] = currentWord.getCodes().get(p);
            idxSyn1[p] = currentWord.getPoints().get(p);
        }
    } else {
        idxSyn1 = new int[0];
        codes = new byte[0];
    }


    if (negative > 0) {
        if (syn1Neg == null) {
            ((InMemoryLookupTable<T>) lookupTable).initNegative();
            syn1Neg = new DeviceLocalNDArray(((InMemoryLookupTable<T>) lookupTable).getSyn1Neg());
        }
    }

    if (batches.get() == null)
        batches.set(new ArrayList<Aggregate>());

    /*AggregateCBOW(syn0.get(), syn1.get(), syn1Neg.get(), expTable.get(), table.get(),
            currentWord.getIndex(), windowWords, idxSyn1, codes, (int) negative, currentWord.getIndex(),
            lookupTable.layerSize(), alpha, nextRandom.get(), vocabCache.numWords(), numLabels, trainWords,
            inferenceVector);*/

    boolean useHS = configuration.isUseHierarchicSoftmax();
    boolean useNegative = configuration.getNegative() > 0;

    int[] inputStatuses = new int[windowWords.length];
    for (int i = 0; i < windowWords.length; ++i) {
        if (i < wordStatuses.length)
            inputStatuses[i] = wordStatuses[i] ? 1 : 0;
        else
            inputStatuses[i] = -1;
    }
    INDArray wordsStatuses = Nd4j.createFromArray(inputStatuses);

    CbowRound cbow = null;

    if (useHS && useNegative) {
        cbow = new CbowRound(Nd4j.scalar(currentWord.getIndex()), Nd4j.createFromArray(windowWords),
                wordsStatuses,
                Nd4j.scalar(currentWord.getIndex()),
                syn0.get(), syn1.get(), syn1Neg.get(),
                expTable.get(), table.get(), Nd4j.createFromArray(idxSyn1), Nd4j.createFromArray(codes),
                (int)negative, Nd4j.scalar(alpha), Nd4j.scalar(nextRandom.get()),
                inferenceVector != null ? inferenceVector : Nd4j.empty(syn0.get().dataType()),
                Nd4j.empty(DataType.INT),
                trainWords,
                workers);
    }
    else if (useHS) {
        cbow = new CbowRound(currentWord.getIndex(), windowWords, wordsStatuses.toIntVector(),
                syn0.get(), syn1.get(),
                expTable.get(), idxSyn1, codes, alpha, nextRandom.get(),
                inferenceVector != null ? inferenceVector : Nd4j.empty(syn0.get().dataType()), 0);
    }
    else if (useNegative) {
        cbow = new CbowRound(currentWord.getIndex(), windowWords, wordsStatuses.toIntVector(), currentWord.getIndex(),
                syn0.get(), syn1Neg.get(),
                expTable.get(), table.get(), (int)negative, alpha, nextRandom.get(),
                inferenceVector != null ? inferenceVector : Nd4j.empty(syn0.get().dataType()), 0);
    }

    nextRandom.set(Math.abs(nextRandom.get() * 25214903917L + 11));
    Nd4j.getExecutioner().exec(cbow);

    /*if (!isInference) {
        batches.get().add(cbow);
        if (batches.get().size() > 4096) {
            Nd4j.getExecutioner().exec(batches.get());
            batches.get().clear();
        }
    } else
        Nd4j.getExecutioner().exec(cbow);*/

}
 
源代码15 项目: Chronicle-Queue   文件: JDBCServiceTest.java
private void doCreateTable(int repeats, int noUpdates) {
    for (int t = 0; t < repeats; t++) {
        long start = System.nanoTime(), written;
        File path1 = DirectoryUtils.tempDir("createTable1");
        File path2 = DirectoryUtils.tempDir("createTable2");
        File file = new File(OS.TARGET, "hsqldb-" + System.nanoTime());
        file.deleteOnExit();

        try (ChronicleQueue in = SingleChronicleQueueBuilder
                .binary(path1)
                .testBlockSize()
                .build();
             ChronicleQueue out = SingleChronicleQueueBuilder
                     .binary(path2)
                     .testBlockSize()
                     .build()) {

            JDBCService service = new JDBCService(in, out, () -> DriverManager.getConnection("jdbc:hsqldb:file:" + file.getAbsolutePath(), "SA", ""));

            JDBCStatement writer = service.createWriter();
            writer.executeUpdate("CREATE TABLE tableName (\n" +
                    "name VARCHAR(64) NOT NULL,\n" +
                    "num INT\n" +
                    ")\n");

            for (int i = 1; i < (long) noUpdates; i++)
                writer.executeUpdate("INSERT INTO tableName (name, num)\n" +
                        "VALUES (?, ?)", "name", i);

            written = System.nanoTime() - start;
            AtomicLong queries = new AtomicLong();
            AtomicLong updates = new AtomicLong();
            CountingJDBCResult countingJDBCResult = new CountingJDBCResult(queries, updates);
            MethodReader methodReader = service.createReader(countingJDBCResult);
            while (updates.get() < noUpdates) {
                if (!methodReader.readOne())
                    Thread.yield();
            }
            Closeable.closeQuietly(service);

            long time = System.nanoTime() - start;
            System.out.printf("Average time to write each update %.1f us, average time to perform each update %.1f us%n",
                    written / noUpdates / 1e3,
                    time / noUpdates / 1e3);
        } finally {
            try {
                IOTools.deleteDirWithFiles(path1, 2);
                IOTools.deleteDirWithFiles(path2, 2);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
 
源代码16 项目: mtas   文件: CodecSearchTree.java
/**
 * Gets the mtas tree item.
 *
 * @param ref the ref
 * @param isSinglePoint the is single point
 * @param isStoreAdditionalIdAndRef the is store additional id and ref
 * @param nodeRefApproxOffset the node ref approx offset
 * @param in the in
 * @param objectRefApproxOffset the object ref approx offset
 * @return the mtas tree item
 * @throws IOException Signals that an I/O exception has occurred.
 */
private static MtasTreeItem getMtasTreeItem(Long ref,
    AtomicBoolean isSinglePoint, AtomicBoolean isStoreAdditionalIdAndRef,
    AtomicLong nodeRefApproxOffset, IndexInput in, long objectRefApproxOffset)
    throws IOException {
  try {
    Boolean isRoot = false;
    if (nodeRefApproxOffset.get() < 0) {
      isRoot = true;
    }
    in.seek(ref);
    if (isRoot) {
      nodeRefApproxOffset.set(in.readVLong());
      Byte flag = in.readByte();
      if ((flag
          & MtasTree.SINGLE_POSITION_TREE) == MtasTree.SINGLE_POSITION_TREE) {
        isSinglePoint.set(true);
      }
      if ((flag
          & MtasTree.STORE_ADDITIONAL_ID) == MtasTree.STORE_ADDITIONAL_ID) {
        isStoreAdditionalIdAndRef.set(true);
      }
    }
    int left = in.readVInt();
    int right = in.readVInt();
    int max = in.readVInt();
    Long leftChild = in.readVLong() + nodeRefApproxOffset.get();
    Long rightChild = in.readVLong() + nodeRefApproxOffset.get();
    int size = 1;
    if (!isSinglePoint.get()) {
      size = in.readVInt();
    }
    // initialize
    long[] objectRefs = new long[size];
    int[] objectAdditionalIds = null;
    long[] objectAdditionalRefs = null;
    // get first
    long objectRef = in.readVLong();
    long objectRefPrevious = objectRef + objectRefApproxOffset;
    objectRefs[0] = objectRefPrevious;
    if (isStoreAdditionalIdAndRef.get()) {
      objectAdditionalIds = new int[size];
      objectAdditionalRefs = new long[size];
      objectAdditionalIds[0] = in.readVInt();
      objectAdditionalRefs[0] = in.readVLong();
    }
    // get others
    for (int t = 1; t < size; t++) {
      objectRef = objectRefPrevious + in.readVLong();
      objectRefs[t] = objectRef;
      objectRefPrevious = objectRef;
      if (isStoreAdditionalIdAndRef.get()) {
        objectAdditionalIds[t] = in.readVInt();
        objectAdditionalRefs[t] = in.readVLong();
      }
    }
    return new MtasTreeItem(left, right, max, objectRefs, objectAdditionalIds,
        objectAdditionalRefs, ref, leftChild, rightChild);
  } catch (Exception e) {
    throw new IOException(e.getMessage());
  }
}
 
源代码17 项目: jdk8u-jdk   文件: ForkJoinPool.java
/**
 * Returns a string identifying this pool, as well as its state,
 * including indications of run state, parallelism level, and
 * worker and task counts.
 *
 * @return a string identifying this pool, as well as its state
 */
public String toString() {
    // Use a single pass through workQueues to collect counts
    long qt = 0L, qs = 0L; int rc = 0;
    AtomicLong sc = stealCounter;
    long st = (sc == null) ? 0L : sc.get();
    long c = ctl;
    WorkQueue[] ws; WorkQueue w;
    if ((ws = workQueues) != null) {
        for (int i = 0; i < ws.length; ++i) {
            if ((w = ws[i]) != null) {
                int size = w.queueSize();
                if ((i & 1) == 0)
                    qs += size;
                else {
                    qt += size;
                    st += w.nsteals;
                    if (w.isApparentlyUnblocked())
                        ++rc;
                }
            }
        }
    }
    int pc = (config & SMASK);
    int tc = pc + (short)(c >>> TC_SHIFT);
    int ac = pc + (int)(c >> AC_SHIFT);
    if (ac < 0) // ignore transient negative
        ac = 0;
    int rs = runState;
    String level = ((rs & TERMINATED) != 0 ? "Terminated" :
                    (rs & STOP)       != 0 ? "Terminating" :
                    (rs & SHUTDOWN)   != 0 ? "Shutting down" :
                    "Running");
    return super.toString() +
        "[" + level +
        ", parallelism = " + pc +
        ", size = " + tc +
        ", active = " + ac +
        ", running = " + rc +
        ", steals = " + st +
        ", tasks = " + qt +
        ", submissions = " + qs +
        "]";
}
 
源代码18 项目: lucene-solr   文件: TestIndexWriter.java
public void testMaxCompletedSequenceNumber() throws IOException, InterruptedException {
  try (Directory dir = newDirectory();
       IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig());) {
    assertEquals(1, writer.addDocument(new Document()));
    assertEquals(2, writer.updateDocument(new Term("foo", "bar"), new Document()));
    writer.flushNextBuffer();
    assertEquals(3, writer.commit());
    assertEquals(4, writer.addDocument(new Document()));
    assertEquals(4, writer.getMaxCompletedSequenceNumber());
    // commit moves seqNo by 2 since there is one DWPT that could still be in-flight
    assertEquals(6, writer.commit());
    assertEquals(6, writer.getMaxCompletedSequenceNumber());
    assertEquals(7, writer.addDocument(new Document()));
    writer.getReader().close();
    // getReader moves seqNo by 2 since there is one DWPT that could still be in-flight
    assertEquals(9, writer.getMaxCompletedSequenceNumber());
  }
  try (Directory dir = newDirectory();
       IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig());
       SearcherManager manager = new SearcherManager(writer, new SearcherFactory())) {
    CountDownLatch start = new CountDownLatch(1);
    int numDocs = 100 + random().nextInt(500);
    AtomicLong maxCompletedSeqID = new AtomicLong(-1);
    Thread[] threads = new Thread[2 + random().nextInt(2)];
    for (int i = 0; i < threads.length; i++) {
      int idx = i;
      threads[i] = new Thread(() -> {
        try {
          start.await();
          for (int j = 0; j < numDocs; j++) {
            Document doc = new Document();
            String id = idx +"-"+j;
            doc.add(new StringField("id", id, Field.Store.NO));
            long seqNo = writer.addDocument(doc);
            if (maxCompletedSeqID.get() < seqNo) {
              long maxCompletedSequenceNumber = writer.getMaxCompletedSequenceNumber();
              manager.maybeRefreshBlocking();
              maxCompletedSeqID.updateAndGet(oldVal-> Math.max(oldVal, maxCompletedSequenceNumber));
            }
            IndexSearcher acquire = manager.acquire();
            try {
              assertEquals(1, acquire.search(new TermQuery(new Term("id", id)), 10).totalHits.value);
            } finally {
              manager.release(acquire);
            }
          }
        } catch (Exception e) {
          throw new AssertionError(e);
        }
      });
      threads[i].start();
    }
    start.countDown();
    for (int i = 0; i < threads.length; i++) {
      threads[i].join();
    }
  }
}
 
源代码19 项目: jdk8u-jdk   文件: ForkJoinPool.java
/**
 * Returns a string identifying this pool, as well as its state,
 * including indications of run state, parallelism level, and
 * worker and task counts.
 *
 * @return a string identifying this pool, as well as its state
 */
public String toString() {
    // Use a single pass through workQueues to collect counts
    long qt = 0L, qs = 0L; int rc = 0;
    AtomicLong sc = stealCounter;
    long st = (sc == null) ? 0L : sc.get();
    long c = ctl;
    WorkQueue[] ws; WorkQueue w;
    if ((ws = workQueues) != null) {
        for (int i = 0; i < ws.length; ++i) {
            if ((w = ws[i]) != null) {
                int size = w.queueSize();
                if ((i & 1) == 0)
                    qs += size;
                else {
                    qt += size;
                    st += w.nsteals;
                    if (w.isApparentlyUnblocked())
                        ++rc;
                }
            }
        }
    }
    int pc = (config & SMASK);
    int tc = pc + (short)(c >>> TC_SHIFT);
    int ac = pc + (int)(c >> AC_SHIFT);
    if (ac < 0) // ignore transient negative
        ac = 0;
    int rs = runState;
    String level = ((rs & TERMINATED) != 0 ? "Terminated" :
                    (rs & STOP)       != 0 ? "Terminating" :
                    (rs & SHUTDOWN)   != 0 ? "Shutting down" :
                    "Running");
    return super.toString() +
        "[" + level +
        ", parallelism = " + pc +
        ", size = " + tc +
        ", active = " + ac +
        ", running = " + rc +
        ", steals = " + st +
        ", tasks = " + qt +
        ", submissions = " + qs +
        "]";
}
 
源代码20 项目: jdk1.8-source-analysis   文件: Random.java
/**
 * Generates the next pseudorandom number. Subclasses should
 * override this, as this is used by all other methods.
 *
 * <p>The general contract of {@code next} is that it returns an
 * {@code int} value and if the argument {@code bits} is between
 * {@code 1} and {@code 32} (inclusive), then that many low-order
 * bits of the returned value will be (approximately) independently
 * chosen bit values, each of which is (approximately) equally
 * likely to be {@code 0} or {@code 1}. The method {@code next} is
 * implemented by class {@code Random} by atomically updating the seed to
 *  <pre>{@code (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)}</pre>
 * and returning
 *  <pre>{@code (int)(seed >>> (48 - bits))}.</pre>
 *
 * This is a linear congruential pseudorandom number generator, as
 * defined by D. H. Lehmer and described by Donald E. Knuth in
 * <i>The Art of Computer Programming,</i> Volume 3:
 * <i>Seminumerical Algorithms</i>, section 3.2.1.
 *
 * @param  bits random bits
 * @return the next pseudorandom value from this random number
 *         generator's sequence
 * @since  1.1
 */
protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}