I have this program in Java import java.util.*;
public class Euclid {
private static final String EXCEPTION_MSG =
"Invalid value (%d); only positive integers are allowed. ";
public static int getGcd( int a, int b)
{
if (a < 0)
{
throw new IllegalArgumentException(String.format(EXCEPTION_MSG, a));
}
else
if (b < 0)
{
throw new IllegalArgumentException(String.format(EXCEPTION_MSG, b));
}
while (b != 0)
{
if (a > b)
{
a = a - b;
}
else
{
b = b - a;
}
}
return a;
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class EuclidGui
{
private static final String PROMPT_A = "#1";
private static final String PROMPT_B = "#2";
private static final String BUTTON_TEXT = "Get GCD >>";
private static final String EXCEPTION_TITLE = "Input Exception";
private static final String INSTRUCTIONS = "Type to integer and press 'Get GCD'";
private static final String DIALOG_TITLE = "Euclid's Algorithm";
private static final int FIELD_WIDTH = 6;
public static void main (String[] args)
{
final JTextField valueA = new JTextField (FIELD_WIDTH);
final JTextField valueB = new JTextField (FIELD_WIDTH);
final JTextField valueGcd = new JTextField (FIELD_WIDTH);
JLabel labelA = new JLabel(PROMPT_A);
JLabel labelB = new JLabel(PROMPT_B);
JButton computeButton = new JButton(BUTTON_TEXT);
Object[] options = new Object[] {labelA, valueA, labelB, valueB, computeButton, valueGcd};
valueGcd.setEditable (false);
computeButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{ try
{
int a = Integer.parseInt(valueA.getText());
int b = Integer.parseInt(valueB.getText());
int gcd = Euclid.getGcd(a , b);
valueGcd.setText(Integer.toString(gcd));
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null, e.getMessage(), EXCEPTION_TITLE, JOptionPane.ERROR_MESSAGE);
}
}
});
JOptionPane.showOptionDialog(null, INSTRUCTIONS, DIALOG_TITLE, JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE,
null, options, null);
}
}
and I want to add calculation time code on it but I have no Idea how, and what is the correct code that I use.Please help me if any one have an Idea.
System.currentTimeMillis() would do the trick:
long start = System.currentTimeMillis();
// do stuff
long timeTaken = System.currentTimeMillis() - start;
The chances are that a single call to getGcd will take so little time that you will have difficulty measuring it reliable and accurately.
The System.currentTimeMillis() method will give you the wall clock time measured in milliseconds. However, the granularity of the millisecond clock is probably too coarse. (Read the javadoc!).
The System.nanoTime() method gives a system time with (as the javadoc says) "nanosecond precision, but not necessarily nanosecond accuracy.".
There are also issues with nanoTime() on multicore machines with some operating systems. For instance, I've heard that different cores can have independent nanoTime clocks that can drift with respect to each other. This can result in System.nanoTime() returning values that are non-monotonic; e.g. if the current thread is rescheduled by the OS to run on a different core between two nanoTime() calls.
If I was doing this, I'd put the calls to getGcd() into a loop that ran it 10,000 or 100,000 times, measure the time for the loop, and divide the measured time by the relevant factor.
Related
Have a scenario where multiple threads have race condition on comparison code.
private int volatile maxValue;
private AtomicInteger currentValue;
public void constructor() {
this.current = new AtomicInteger(getNewValue());
}
public getNextValue() {
while(true) {
int latestValue = this.currentValue.get();
int nextValue = latestValue + 1;
if(latestValue == maxValue) {//Race condition 1
latestValue = getNewValue();
}
if(currentValue.compareAndSet(latestValue, nextValue) {//Race condition 2
return latestValue;
}
}
}
private int getNewValue() {
int newValue = getFromDb(); //not idempotent
maxValue = newValue + 10;
return newValue;
}
Questions :
The obvious way to fix this would be add synchronized block/method around the if condition. What are other performant way to fix this using concurrent api without using any kind of locks ?
How to get rid of the while loop so we can get the next value with no or less thread contention ?
Constraints :
The next db sequences will be in increasing order not necessarily evenly distributed. So it could be 1, 11, 31 where 21 may be have asked by other node. The requested next value will always be unique. Also need to make sure all the sequences are used and once we reach the max for previous range then only request to db for another starting sequence and so on.
Example :
for db next sequences 1,11,31 with 10 increment, the output next sequence should be 1-10, 11-20, 31-40 for 30 requests.
First of all: I would recommend thinking one more time about using synchronized, because:
look at how simple such code is:
private int maxValue;
private int currentValue;
public constructor() {
requestNextValue();
}
public synchronized int getNextValue() {
currentValue += 1;
if (currentValue == maxValue) {
requestNextValue();
}
return currentValue;
}
private void requestNextValue() {
currentValue = getFromDb(); //not idempotent
maxValue = currentValue + 10;
}
locks in java actually are pretty intelligent and have pretty good performance.
you talk to DB in your code — the performance cost of that alone can be orders of magnitude higher than the performance cost of locks.
But in general, your race conditions happen because you update maxValue and currentValue independently.
You can combine these 2 values into a single immutable object and then work with the object atomically:
private final AtomicReference<State> stateHolder = new AtomicReference<>(newStateFromDb());
public int getNextValue() {
while (true) {
State oldState = stateHolder.get();
State newState = (oldState.currentValue == oldState.maxValue)
? newStateFromDb()
: new State(oldState.currentValue + 1, oldState.maxValue);
if (stateHolder.compareAndSet(oldState, newState)) {
return newState.currentValue;
}
}
}
private static State newStateFromDb() {
int newValue = getFromDb(); // not idempotent
return new State(newValue, newValue + 10);
}
private static class State {
final int currentValue;
final int maxValue;
State(int currentValue, int maxValue) {
this.currentValue = currentValue;
this.maxValue = maxValue;
}
}
After fixing that you will probably have to solve the following problems next:
how to prevent multiple parallel getFromDb(); (especially after taking into account that the method is idempotent)
when one thread performs getFromDb();, how to prevent other threads from busy spinning inside while(true) loop and consuming all available cpu time
more similar problems
Solving each of these problems will probably make your code more and more complicated.
So, IMHO it is almost never worth it — locks work fine and keep the code simple.
You cannot completely avoid locking with the given constraints: since (1) every value returned by getFromDb() must be used and (2) calling getFromDb() is only allowed once maxValue has been reached, you need to ensure mutual exclusion for calls to getFromDb().
Without either of the constraints (1) or (2) you could resort to optimistic locking though:
Without (1) you could allow multiple threads calling getFromDb() concurrently and choose one of the results dropping all others.
Without (2) you could allow multiple threads calling getFromDb() concurrently and choose one of the results. The other results would be "saved for later".
The obvious way to fix this would be add synchronized block around the if condition
That is not going to work. Let me try and explain.
When you hit the condition: if(latestValue == maxValue) { ... }, you want to update both maxValue and currentValue atomically. Something like this:
latestValue = getNewValue();
currentValue.set(latestValue);
getNewValue will get your next starting value from the DB and update maxValue, but at the same time, you want to set currentValue to that new starting one now. Suppose the case:
you first read 1 from the DB. As such maxValue = 11, currentValue = 1.
when you reach the condition if(latestValue == maxValue), you want to go to the DB to get the new starting position (let's say 21), but at the same time you want every thread to now start from 21. So you must also set currentValue.
Now the problem is that if you write to currentValue under a synchronized block, for example:
if(latestValue == maxValue) {
synchronized (lock) {
latestValue = getNewValue();
currentValue.set(latestValue);
}
}
you also need to read under the same lock, otherwise you have race. Initially I thought I can be a bit smarter and do something like:
if(latestValue == maxValue) {
synchronized (lock) {
if(latestValue == maxValue) {
latestValue = getNewValue();
currentValue.set(latestValue);
} else {
continue;
}
}
}
So that all threads that wait on a lock do not override the previously written value to maxValue when the lock is released. But that still is a race and will cause problems elsewhere, in a different case, rather trivially. For example:
ThreadA does latestValue = getNewValue();, thus maxValue == 21. Before it does currentValue.set(latestValue);
ThreadB reads int latestValue = this.currentValue.get();, sees 11 and of course this will be false : if(latestValue == maxValue) {, so it can write 12 (nextValue) to currentValue. Which breaks the entire algorithm.
I do not see any other way then to make getNextValue synchronized or somehow else protected by a mutex/spin-lock.
I don't really see a way around synchonizing the DB call - unless calling the DB multiple times is not an issue (i.e. retrieving several "new values").
To remove the need to synchronize the getNextValue method, you could use a BlockingQueue which will remove the need to atomically update 2 variables. And if you really don't want to use the synchronize keyword, you can use a flag to only let one thread call the DB.
It could look like this (looks ok, but not tested):
private final BlockingQueue<Integer> nextValues = new ArrayBlockingQueue<>(10);
private final AtomicBoolean updating = new AtomicBoolean();
public int getNextValue() {
while (true) {
Integer nextValue = nextValues.poll();
if (nextValue != null) return nextValue;
else getNewValues();
}
}
private void getNewValues() {
if (updating.compareAndSet(false, true)) {
//we hold the "lock" to run the update
if (!nextValues.isEmpty()) {
updating.set(false);
throw new IllegalStateException("nextValues should be empty here");
}
try {
int newValue = getFromDb(); //not idempotent
for (int i = 0; i < 10; i++) {
nextValues.add(newValue + i);
}
} finally {
updating.set(false);
}
}
}
But as mentioned in other comments, there is a high chance that the most costly operation here is the DB call, which remains synchronized, so you may as well synchronize everything and keep it simple, with very little difference performance wise.
As getFromDb hits the database you really want some locking - the other threads should block not also go for the database or spin. Really, if you are doing that every 10 iterations, you can probably synchronize the lot. However, that is no fun.
Any reasonable, non-microcontroller platform should support AtomicLong as lock-free. So we can conveniently pack the two ints into one atomic.
private final AtomicLong combinedValue;
public getNextValue() {
for (;;) {
long combined = combinedValue.get();
int latestValue = (int)combined;
int maxValue = (int)(combined>>32);
int nextValue = latestValue + 1;
long nextCombined = (newValue&0xffffffff) | (maxValue<<32)
if (latestValue == maxValue) {
nextValue();
} else if (currentValue.compareAndSet(combined, nextCombined)) {
return latestValue;
}
}
}
private synchronized void nextValue() {
// Yup, we need to double check with this locking.
long combined = combinedValue.get();
int latestValue = (int)combined;
int maxValue = (int)(combined>>32);
if (latestValue == maxValue) {
int newValue = getFromDb(); //not idempotent
int maxValue = newValue + 10;
long nextCombined = (newValue&0xffffffff) | (maxValue<<32)
combinedValue.set(nextCombined);
}
}
An alternative with memory allocation would be to lump both values into one object and use AtomicReference. However, we can observe that the value changes more frequently than the maximum, so we can use a slow changing object and a fast offset.
private static record Segment(
int maxValue, AtomicInteger currentValue
) {
}
private volatile Segment segment;
public getNextValue() {
for (;;) {
Segment segment = this.segment;
int latestValue = segment.currentValue().get();
int nextValue = latestValue + 1;
if (latestValue == segment.maxValue()) {
nextValue();
} else if (segment.currentValue().compareAndSet(
latestValue, nextValue
)) {
return latestValue;
}
}
}
private synchronized void nextValue() {
// Yup, we need to double check with this locking.
Segment segment = this.segment;
int latestValue = segment.currentValue().get();
if (latestValue == segment.maxValue()) {
int newValue = getFromDb(); //not idempotent
int maxValue = newValue + 10;
segment = new Segment(maxValue, new AtomicInteger(newValue));
}
}
(Standard disclaimer: Code not so much as compiled, tested or thought about much. records require a quite new at time of writing JDK. Constructors elided.)
What an interesting question. As others have said you get round with your problem by using synchronized keyword.
public synchronized int getNextValue() { ... }
But because you didn't want to use that keyword and at the same time want to avoid race condition, this probably helps. No guarantee though. And please don't ask for explanations, I'll throw you with OutOfBrainException.
private volatile int maxValue;
private volatile boolean locked = false; //For clarity.
private AtomicInteger currentValue;
public int getNextValue() {
int latestValue = this.currentValue.get();
int nextValue = latestValue + 1;
if(!locked && latestValue == maxValue) {
locked = true; //Only one thread per time.
latestValue = getNewValue();
currentValue.set(latestValue);
locked = false;
}
while(locked) { latestValue = 0; } //If a thread running in the previous if statement, we need this to buy some time.
//We also need to reset "latestValue" so that when this thread runs the next loop,
//it will guarantee to call AtomicInteger.get() for the updated value.
while(!currentValue.compareAndSet(latestValue, nextValue)) {
latestValue = this.currentValue.get();
nextValue = latestValue + 1;
}
return nextValue;
}
Or you can use Atomic to fight Atomic.
private AtomicBoolean locked = new AtomicBoolean(false);
public int getNextValue() {
...
if(locked.compareAndSet(false, true)) { //Only one thread per time.
if(latestValue == maxValue) {
latestValue = getNewValue();
currentValue.set(latestValue);
}
locked.set(false);
}
...
I can't think of a way to remove all locking since the underlying problem is accessing a mutable value from several threads. However there several improvements that can be done to the code you provided, basically taking advantage of the fact that when data is read by multiple threads, there is no need to lock the reads unless a write has to be done, so using Read/Write locks will reduce the contention. Only 1/10 times there will be a "full" write lock
So the code could be rewritten like this (leaving bugs aside):
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Counter {
private final ReentrantReadWriteLock reentrantLock = new ReentrantReadWriteLock(true);
private final ReentrantReadWriteLock.ReadLock readLock = reentrantLock.readLock();
private final ReentrantReadWriteLock.WriteLock writeLock = reentrantLock.writeLock();
private AtomicInteger currentValue;
private AtomicInteger maxValue;
public Counter() {
int initialValue = getFromDb();
this.currentValue = new AtomicInteger(initialValue);
this.maxValue = new AtomicInteger(initialValue + 10);
}
public int getNextValue() {
readLock.lock();
while (true){
int nextValue = currentValue.getAndIncrement();
if(nextValue<maxValue.get()){
readLock.unlock();
return nextValue;
}
else {
readLock.unlock();
writeLock.lock();
reload();
readLock.lock();
writeLock.unlock();
}
}
}
private void reload(){
int newValue = getFromDb();
if(newValue>maxValue.get()) {
this.currentValue.set(newValue);
this.maxValue.set(newValue + 10);
}
}
private int getFromDb(){
// your implementation
}
}
What is the business use case you are trying to solve?
Can the next scenario work for you:
Create SQL sequence (based your database) with counter requirements in the database;
Fetch counters from the database as a batch like 50-100 ids
Once 50-100 are used on the app level, fetch 100 values more from db ...
?
Slightly modified version of user15102975's answer with no while-loop and getFromDb() mock impl.
/**
* Lock free sequence counter implementation
*/
public class LockFreeSequenceCounter {
private static final int BATCH_SIZE = 10;
private final AtomicReference<Sequence> currentSequence;
private final ConcurrentLinkedQueue<Integer> databaseSequenceQueue;
public LockFreeSequenceCounter() {
this.currentSequence = new AtomicReference<>(new Sequence(0,0));
this.databaseSequenceQueue = new ConcurrentLinkedQueue<>();
}
/**
* Get next unique id (threadsafe)
*/
public int getNextValue() {
return currentSequence.updateAndGet((old) -> old.next(this)).currentValue;
}
/**
* Immutable class to handle current and max value
*/
private static final class Sequence {
private final int currentValue;
private final int maxValue;
public Sequence(int currentValue, int maxValue) {
this.currentValue = currentValue;
this.maxValue = maxValue;
}
public Sequence next(LockFreeSequenceCounter counter){
return isMaxReached() ? fetchDB(counter) : inc();
}
private boolean isMaxReached(){
return currentValue == maxValue;
}
private Sequence inc(){
return new Sequence(this.currentValue + 1, this.maxValue);
}
private Sequence fetchDB(LockFreeSequenceCounter counter){
counter.databaseSequenceQueue.add(counter.getFromDb());
int newValue = counter.databaseSequenceQueue.poll();
int maxValue = newValue + BATCH_SIZE -1;
return new Sequence(newValue, maxValue);
}
}
/**
* Get unique id from db (mocked)
* return on call #1: 1
* return on call #2: 11
* return on call #3: 31
* Note: this function is not idempotent
*/
private int getFromDb() {
if (dbSequencer.get() == 21){
return dbSequencer.addAndGet(BATCH_SIZE);
} else{
return dbSequencer.getAndAdd(BATCH_SIZE);
}
}
private final AtomicInteger dbSequencer = new AtomicInteger(1);
}
Slightly modified version of Tom Hawtin - tackline's answer and also the suggestion by codeflush.dev in the comments of the question
Code
I have added a working version of code and simulated a basic multithreaded environment.
Disclaimer: Use with your own discretion
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Seed {
private static final int MSB = 32;
private final int start;
private final int end;
private final long window;
public Seed(int start, int end) {
this.start = start;
this.end = end;
this.window = (((long) end) << MSB) | start;
}
public Seed(long window) {
this.start = (int) window;
this.end = (int) (window >> MSB);
this.window = window;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public long getWindow() {
return window;
}
// this will not update the state, will only return the computed value
public long computeNextInWindow() {
return window + 1;
}
}
// a mock external seed service to abstract the seed generation and window logic
class SeedService {
private static final int SEED_INIT = 1;
private static final AtomicInteger SEED = new AtomicInteger(SEED_INIT);
private static final int SEQ_LENGTH = 10;
private static final int JITTER_FACTOR = 5;
private final boolean canAddRandomJitterToSeed;
private final Random random;
public SeedService(boolean canJitterSeed) {
this.canAddRandomJitterToSeed = canJitterSeed;
this.random = new Random();
}
public int getSeqLengthForTest() {
return SEQ_LENGTH;
}
public Seed getDefaultWindow() {
return new Seed(1, 1);
}
public Seed getNextWindow() {
int offset = SEQ_LENGTH;
// trying to simulate multiple machines with interleaved start seed
if (canAddRandomJitterToSeed) {
offset += random.nextInt(JITTER_FACTOR) * SEQ_LENGTH;
}
final int start = SEED.getAndAdd(offset);
return new Seed(start, start + SEQ_LENGTH);
}
// helper to validate generated ids
public boolean validate(List<Integer> ids) {
Collections.sort(ids);
// unique check
if (ids.size() != new HashSet<>(ids).size()) {
return false;
}
for (int startIndex = 0; startIndex < ids.size(); startIndex += SEQ_LENGTH) {
if (!checkSequence(ids, startIndex)) {
return false;
}
}
return true;
}
// checks a sequence
// relies on 'main' methods usage of SEQ_LENGTH
protected boolean checkSequence(List<Integer> ids, int startIndex) {
final int startRange = ids.get(startIndex);
return IntStream.range(startRange, startRange + SEQ_LENGTH).boxed()
.collect(Collectors.toList())
.containsAll(ids.subList(startIndex, startIndex + SEQ_LENGTH));
}
public void shutdown() {
SEED.set(SEED_INIT);
System.out.println("See you soon!!!");
}
}
class SequenceGenerator {
private final SeedService seedService;
private final AtomicLong currentWindow;
public SequenceGenerator(SeedService seedService) {
this.seedService = seedService;
// initialize currentWindow using seedService
// best to initialize to an old window so that every instance of SequenceGenerator
// will lazy load from seedService during the first getNext() call
currentWindow = new AtomicLong(seedService.getDefaultWindow().getWindow());
}
public synchronized boolean requestSeed() {
Seed seed = new Seed(currentWindow.get());
if (seed.getStart() == seed.getEnd()) {
final Seed nextSeed = seedService.getNextWindow();
currentWindow.set(nextSeed.getWindow());
return true;
}
return false;
}
public int getNext() {
while (true) {
// get current window
Seed seed = new Seed(currentWindow.get());
// exhausted and need to seed again
if (seed.getStart() == seed.getEnd()) {
// this will loop at least one more time to return value
requestSeed();
} else if (currentWindow.compareAndSet(seed.getWindow(), seed.computeNextInWindow())) {
// successfully incremented value for next call. so return current value
return seed.getStart();
}
}
}
}
public class SequenceGeneratorTest {
public static void test(boolean canJitterSeed) throws Exception {
// just some random multithreaded invocation
final int EXECUTOR_THREAD_COUNT = 10;
final Random random = new Random();
final int INSTANCES = 500;
final SeedService seedService = new SeedService(canJitterSeed);
final int randomRps = 500;
final int seqLength = seedService.getSeqLengthForTest();
ExecutorService executorService = Executors.newFixedThreadPool(EXECUTOR_THREAD_COUNT);
Callable<List<Integer>> callable = () -> {
final SequenceGenerator generator = new SequenceGenerator(seedService);
int rps = (1 + random.nextInt(randomRps)) * seqLength;
return IntStream.range(0, rps).parallel().mapToObj(i -> generator.getNext())
.collect(Collectors.toList());
};
List<Future<List<Integer>>> futures = IntStream.range(0, INSTANCES).parallel()
.mapToObj(i -> executorService.submit(callable))
.collect(Collectors.toList());
List<Integer> ids = new ArrayList<>();
for (Future<List<Integer>> f : futures) {
ids.addAll(f.get());
}
executorService.shutdown();
// validate generated ids for correctness
if (!seedService.validate(ids)) {
throw new IllegalStateException();
}
seedService.shutdown();
// summary
System.out.println("count: " + ids.size() + ", unique count: " + new HashSet<>(ids).size());
Collections.sort(ids);
System.out.println("min id: " + ids.get(0) + ", max id: " + ids.get(ids.size() - 1));
}
public static void main(String[] args) throws Exception {
test(true);
System.out.println("Note: ids can be interleaved. if continuous sequence is needed, initialize SeedService with canJitterSeed=false");
final String ruler = Collections.nCopies( 50, "-" ).stream().collect( Collectors.joining());
System.out.println(ruler);
test(false);
System.out.println("Thank you!!!");
System.out.println(ruler);
}
}
I am experiencing a weird behavior with Java objects. I have this ComponentPlane.class with two different versions. Difference is marked by ******.
First WORKING Version
package app.pathsom.som.output;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
import app.pathsom.som.map.Lattice;
import app.pathsom.som.map.Node;
public class ComponentPlane extends JPanel{
private Lattice lattice;
private int componentNumber;
private double minValue;
private double maxValue;
private double origMinValue;
private double origMaxValue;
public ComponentPlane(Lattice lattice, int componentNumber){
this.lattice = new Lattice();
this.componentNumber = componentNumber;
initLattice(lattice);
initComponentPlane();
}
private void initLattice(Lattice lattice){
this.lattice.setLatticeHeight(lattice.getLatticeHeight());
this.lattice.setLatticeWidth(lattice.getLatticeWidth());
this.lattice.setNumberOfNodeElements(lattice.getNumberOfNodeElements());
this.lattice.initializeValues();
this.lattice.setNodeHeight(lattice.getNodeHeight());
this.lattice.setNodeWidth(lattice.getNodeWidth());
this.lattice.setTotalNumberOfNodes(lattice.getTotalNumberOfNodes());
for(int i = 0; i < lattice.getTotalNumberOfNodes(); i++){
******this.lattice.getLatticeNode()[i] = new Node(lattice.getLatticeNode()[i]);******
}
}
}
The only difference of the second NON-WORKING version is with this FUNCTION REPLACING the FUNCTION above
private void initLattice(Lattice lattice){
//same code here
for(int i = 0; i < lattice.getTotalNumberOfNodes(); i++){
******this.lattice.getLatticeNode()[i] = lattice.getLatticeNode()[i];******
}
}
I have also tried doing a third non-working version which is...
private void initLattice(Lattice lattice){
//same code here
******this.lattice.setLatticeNode(lattice.getLatticeNode());******
}
A constructor in the Node.class (WHICH is USED in the first WORKING version is this one...
public Node (Node node){
this.xPos = node.xPos;
this.yPos = node.yPos;
this.numOfElements = node.numOfElements;
this.cluster = -1;
this.nodeIndex = node.getNodeIndex();
for(int i = 0; i < this.numOfElements; i++){
this.addElement(node.getDoubleElementAt(i));
}
}
Lattice.class
public class Lattice {
private int latticeWidth;
private int latticeHeight;
private int numOfNodeElements;
private int nodeWidth;
private int nodeHeight;
private int totalNumOfNodes;
private Node[] latticeNodes;
private final int MAP_RADIUS = 225;
public Lattice(int latticeWidth, int latticeHeight, int numOfNodeElements){
this.latticeWidth = latticeWidth;
this.latticeHeight = latticeHeight;
this.numOfNodeElements = numOfNodeElements;
initializeLattice();
}
public Lattice(){
this(10, 10, 3);
}
public void initializeValues(){
totalNumOfNodes = this.latticeHeight * this.latticeWidth;
latticeNodes = new Node[totalNumOfNodes]; //specify the array of nodes
nodeWidth = (int) Math.floor(450/this.latticeWidth);
nodeHeight = (int) Math.floor(450/this.latticeHeight);
}
protected void initializeLattice(){
totalNumOfNodes = this.latticeHeight * this.latticeWidth;
latticeNodes = new Node[totalNumOfNodes];
nodeWidth = (int) Math.floor(450/this.latticeWidth);
nodeHeight = (int) Math.floor(450/this.latticeHeight);
//initialize colors
for(int i = 0; i <totalNumOfNodes; i++){
latticeNodes[i] = new Node(((i % this.latticeWidth) * nodeWidth) + nodeWidth / 2,
((i / this.latticeWidth) * nodeHeight ) + nodeHeight/2, numOfNodeElements, i);
latticeNodes[i].setNodeColor(new Color((int)(latticeNodes[i].getDoubleElementAt(0)
* 255), (int)(latticeNodes[i].getDoubleElementAt(1) * 255), (int) (latticeNodes[i].getDoubleElementAt(2) * 255)));
}
}
public int getLatticeHeight(){
return latticeHeight;
}
public void setLatticeHeight(int latticeHeight){
this.latticeHeight = latticeHeight;
}
public Node[] getLatticeNode(){
return latticeNodes;
}
public void setLatticeNode(Node[] latticeNodes){
this.latticeNodes = latticeNodes;
}
public int getLatticeWidth(){
return latticeWidth;
}
public void setLatticeWidth(int latticeWidth){
this.latticeWidth = latticeWidth;
}
public int getNodeHeight(){
return nodeHeight;
}
public int getNodeWidth(){
return nodeWidth;
}
public void setNodeHeight(int nodeHeight){
this.nodeHeight = nodeHeight;
}
public void setNodeWidth(int nodeWidth){
this.nodeWidth = nodeWidth;
}
public int getNumberOfNodeElements(){
return numOfNodeElements;
}
public void setNumberOfNodeElements(int numOfNodeElements){
this.numOfNodeElements = numOfNodeElements;
}
public int getTotalNumberOfNodes(){
return totalNumOfNodes;
}
public void setTotalNumberOfNodes(int totalNumberOfNodes){
this.totalNumOfNodes = totalNumberOfNodes;
}
}
A certain Visualization.class initiates all these actions and stores the ComponentPlane arrays. Here is the function
public void initComponentPlanes(){
componentPlanes = new ComponentPlane[somtrainer.getLattice().getNumberOfNodeElements()];
int size = somtrainer.getLattice().getNumberOfNodeElements();
for(int i = 0; i < size; i++){
System.out.println(i + ": " + inputData.getVariableLabels()[i] + " size : " + size);
componentPlanes[i] = new ComponentPlane(somtrainer.getLattice(), i);
componentPlanes[i].setBounds((240 - 225)/2, (280-240)/2, 225, 240);
componentPlanes[i].setOrigMaxMin(maxMin[i][0], maxMin[i][1]);
}
}
My problems are
The First one works fine. It creates HEATMAPS or COMPONENTPLANES for each component number (meaning they differ from each other) but I cannot use it as the line with ****** which references to the ("this.addElement....") in the Node.class constructor gives me OUTOFMEMORY error so it LAGS and FREEZES whenever I have many COMPONENTPLANES to do. (I am actually doing an ARRAY of COMPONENTPlane objects) so I decided to try the second and third option. I have already increased my heap size SO this is OUT of the question
If I use the second and third one, I end up with no LAGS even with large amount of ComponentPlanes (probably less memory taking up because of creating new Node objects or idk) but these creates wrong heatmaps. All heatmaps are the same. And the thing is, all heatmaps are like the last element of the ComponentPlanes array (e.g. if I have ten ComponentPlane objects, all heatmaps look exactly like the tenth Component Object)
All of the heatmaps are like this - the same as the last heatmap in the array:
Is there a way to make the second and third one work?
The obvious difference is that in the first one you're creating new nodes, and in the others you're reusing the old ones. The line
this.lattice.getLatticeNode()[i] = lattice.getLatticeNode()[i];
is setting one object equal to another. If, later, a property of lattice.getLatticeNode()[i] changes, that will also effect this.lattice.getLatticeNode()[i]. And that can cause hard-to-find bugs. In contrast, the line
this.lattice.getLatticeNode()[i] = new Node(lattice.getLatticeNode()[i]);
is creating a new object, distinct from the old one. But, of course, this means that you're using more memory, because now you have two objects instead of one.
There are little things you can do to reduce the amount of memory used. private final int MAP_RADIUS = 225; could be made static, so a new copy of the constant isn't created for each node.
I am compiling a Java program using for loop to find out the biggest value of long. However, nothing was printed when I run the program. Why?
Here's my code:
class LongMaxMin {
public static void main(String args[]) {
long i = 0L;
long result = 0L;
for (; ; ) {
result = i++;
if (i<0)
break;
}
System.out.println("The biggest integer:" + result);
}
Mostly because of time.
A long will have a max of about ~9.22 quintillion. You're starting at zero and incrementing up. That means you need to go through 9 quintillion loops before it wraps over and breaks. I just tried to run 2 billion operations in my javascript console and times out for a couple of minutes before I force quit.
If you sit there and let it run long enough, you'll get your output. Alternatively, start i at something close to the max already, like 9,223,372,036,854,700,000, and see if it still gives you the same issues. In Java 8, adding underscore to numeric literals is allowed. Initializing i to something like 9_223_372_036_854_700_000L will give you something in a more timely manner.
The max long is significantly high, at 9.223372e+18. For specifics, 9,223,372,036,854,775,807 is the number in question. This also contributes to that whole "this works, it'll just take WAY too long" theory.
I was curious how long it would take so I wrote a class to do the same thing. Wrote it with a separate thread to update results to the console every 1 second.
"int" results
1,343,211,433 37.4518434691484288634492200 % left
Max Value: 2,147,483,647
Time Taken (seconds): **1.588**
"long" results
1,220,167,357 99.9999999867709190074470400 % left
2,519,937,368 99.9999999726787843108699600 % left
3,881,970,343 99.9999999579115932059510100 % left
5,210,983,861 99.9999999435023997711689800 % left
6,562,562,290 99.9999999288485570811055300 % left
7,853,387,353 99.9999999148534037050721500 % left
9,137,607,100 99.9999999009298653086103000 % left
10,467,975,104 99.9999998865059865071902600 % left
11,813,910,300 99.9999998719133278719112300 % left
13,183,196,499 99.9999998570674971548090400 % left
...it continues on and on...
1,362,032,97 - difference between the 2nd and 3rd values (1 second)
6,771,768,529 seconds - how many seconds it would take to reach long's max value (Long.MAX_VALUE / 2nd3rdDifference)
6,771,768,529 seconds = 214.73 years (per conversion by google search)
So if my calculations are correct...you'd be dead of old age by the time an average computer calculated the max value of long via incrementing and checking if it's overflowed. Your children would be dead to. Your grandchildren, they might be around when it finished...
Code for Max Value Calculation
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
public class MainLongMaxTest {
// /*
public static final long MAX_VALUE = Long.MAX_VALUE;
public static long value = 0;
public static long previousValue = 0;
// */
/*
public static final int MAX_VALUE = Integer.MAX_VALUE;
public static int value = 0;
public static int previousValue = 0;
*/
public static boolean done;
public static BigDecimal startTime;
public static BigDecimal endTime;
public static void main(String[] args) {
Runnable task = new StatusPrinterRunnable();
new Thread(task).start(); // code waits 1 second before result printing loop
done = false;
startTime = new BigDecimal(System.currentTimeMillis());
while(value >= 0) {
previousValue = value;
value += 1;
}
endTime = new BigDecimal(System.currentTimeMillis());
done = true;
}
}
class StatusPrinterRunnable implements Runnable {
public static final NumberFormat numberFormat = NumberFormat.getNumberInstance();
private static long SLEEP_TIME = 1000;
#Override
public void run() {
try { Thread.sleep(SLEEP_TIME); } catch (InterruptedException e) { throw new RuntimeException(e); }
while(!MainLongMaxTest.done) {
long value = MainLongMaxTest.value;
//long valuesLeft = MAX_VALUE - value;
BigDecimal maxValueBd = new BigDecimal(MainLongMaxTest.MAX_VALUE);
BigDecimal valueBd = new BigDecimal(value);
BigDecimal differenceBd = maxValueBd.subtract(valueBd);
BigDecimal percentLeftBd = differenceBd.divide(maxValueBd, 25, RoundingMode.HALF_DOWN);
percentLeftBd = percentLeftBd.multiply(new BigDecimal(100));
String numberAsString = numberFormat.format(value);
String percentLeftAsString = percentLeftBd.toString();
String message = "" + numberAsString + "\t" + percentLeftAsString + " % left";
System.out.println(message);
try { Thread.sleep(SLEEP_TIME); } catch (InterruptedException e) { throw new RuntimeException(e); }
}
BigDecimal msTaken = MainLongMaxTest.endTime.subtract(MainLongMaxTest.startTime);
BigDecimal secondsTaken = msTaken.divide(new BigDecimal("1000"));
System.out.println();
System.out.println("Max Value: " + numberFormat.format(MainLongMaxTest.previousValue));
System.out.println("Time Taken (seconds): " + secondsTaken);
}
}
I think your logic is correct just it will take a lot of time to reach that value.
the maximum Long value can hold is Long.MAX_value which is 9223372036854775807L
to speed up the logic, I modified the program as below and got the expected result.
public static void main(String args[]) {
long i = 9223372036854775806L;
long result = 0L;
for (; ; ) {
result = i++;
if (i<0) {
System.out.println("result"+result);
System.out.println("i"+i);
break;
}
}
System.out.println("The biggest integer: is" + result);
}
Output:
result9223372036854775807
i-9223372036854775808
The biggest integer: is9223372036854775807
result has the maximum value it can hold after that it changes to its minimum value.
You can get the result in one step if you take advantage of binary algebra by:
result = -1L >>> 1;
I am writing code that is supposed to measure different sort times for different sort methods with arrays of a specific size and display the output time in a GUI. I have got it working for the most part but the program is not displaying the same result each time. For instance, it will say 0.2 milliseconds for one run and 0.1 for the next. I believe the problem is in the runSort() method. Could anybody help me? Here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
import java.util.Arrays;
public class Benchmarks extends JFrame
{
private static int numberOfRuns = 20;
private JTextField arraySizeInput, display;
private String sortMethodNames[] =
{"Selection Sort", "Insertion Sort", "Mergesort", "Quicksort", "Arrays.sort"};
private JComboBox chooseSortMethod;
private final long seed;
private int arraySize;
// Constructor
public Benchmarks()
{
super("Benchmarks");
Container c = getContentPane();
c.setLayout(new GridLayout(6, 1));
c.add(new JLabel(" Array size: "));
arraySizeInput = new JTextField(4);
arraySizeInput.setText("1000");
arraySizeInput.selectAll();
c.add(arraySizeInput);
chooseSortMethod = new JComboBox(sortMethodNames);
c.add(chooseSortMethod);
JButton run = new JButton("Run");
run.addActionListener(new RunButtonListener());
c.add(run);
c.add(new JLabel(" Avg Time (milliseconds): "));
display = new JTextField(" Ready");
display.setBackground(Color.YELLOW);
display.setEditable(false);
c.add(display);
// Use the same random number generator seed for all benchmarks
// in one run of this program:
seed = System.currentTimeMillis();
}
// Fills a[] with random numbers and sorts it using the sorting method
// specified in sortMethod:
// 1 -- Selection Sort
// 2 -- Insertion Sort
// 3 -- Mergesort
// 4 -- Quicksort
// This is repeated numberOfRuns times for better accuracy
// Returns the total time it took in milliseconds.
private long runSort(double[] a, int sortMethod, int numberOfRuns)
{
long startTime;
long endTime;
long diffTime;
Random generator = new Random(seed);
for(int i= a.length-1; i>0; i--)
{
a[i]= generator.nextDouble();
}
startTime= System.currentTimeMillis();
switch(sortMethod)
{
case 1: //Selection Sort
SelectionSort sel = new SelectionSort();
sel.sort(a);
break;
case 2: //Insertion Sort
InsertionSort nsert= new InsertionSort();
nsert.sort(a);
break;
case 3: //Merge Sort
Mergesort merge = new Mergesort();
merge.sort(a);
break;
case 4: // Quick Sort
Quicksort quick = new Quicksort();
quick.sort(a);
break;
}
endTime= System.currentTimeMillis();
diffTime= endTime- startTime;
return diffTime ;
}
// Handles Run button events
private class RunButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String inputStr = arraySizeInput.getText().trim();
try
{
arraySize = Integer.parseInt(inputStr);
}
catch (NumberFormatException ex)
{
display.setText(" Invalid array size");
arraySize = 0;
return;
}
if (arraySize <= 0)
{
display.setText(" Invalid array size");
return;
}
if (arraySize <= 0)
return;
int sortMethod = chooseSortMethod.getSelectedIndex() + 1;
double a[] = new double[arraySize];
double avgTime = (double)runSort(a, sortMethod, numberOfRuns)
/ numberOfRuns;
display.setText(String.format(" %.2f", avgTime));
arraySizeInput.selectAll();
arraySizeInput.requestFocus();
System.out.println("Array size = " + arraySize +
" Runs = " + numberOfRuns + " " +
sortMethodNames[sortMethod - 1] + " avg time: " + avgTime);
}
}
//************************************************************
public static void main(String[] args)
{
numberOfRuns = 20;
if (args.length > 0)
{
int n = -1;
try
{
n = Integer.parseInt(args[0].trim());
}
catch (NumberFormatException ex)
{
System.out.println("Invalid command-line parameter");
System.exit(1);
}
if (n > 0)
numberOfRuns = n;
}
Benchmarks window = new Benchmarks();
window.setBounds(300, 300, 180, 200);
window.setDefaultCloseOperation(EXIT_ON_CLOSE);
window.setVisible(true);
}
}
Thank you for the help.
You are getting different results because of many minor factors, like how busy the computer is at the time. Also, System.currentTimeMillis() is inherently inaccurate; on some systems, 5 ms may be measured as 0 to 10 ms. To get better accuracy when measuring small amounts of time, you should use System.nanoTime(). Also, you should have nothing at all between measuring the start time and measuring the end time. That means no for or while loops, if statements, or switch statements.
What you try is simply not possible. You'll need a system with garanteed cpu time. But scheduling and different loads makes it impossible to get exact times. Additional the Java-Garbage collection and things like optimizing from the java enviroment changes your results. you could use a framework like junitbenchmark and let the code run multible times - but rembemer this will not give you a "really usable" result. It can help you to determ the speed of each algorithm in relation to each other.
I'm pretty new to java and I'm trying to create a program that quizzes users on the difference between 2 random frequencies. Everything works except that when I try to get the difference of 2 frequencies the answer is always 0. How do I get it to display the actual difference? Here is the class I wrote to create the tones ans compute the difference:
public class Quiz{
private PitchPlay one = new PitchPlay();
private PitchPlay two = new PitchPlay();
private int frequencyOne;
private int frequencyTwo;
private int dif = new Integer(Math.abs(frequencyTwo - frequencyOne));
public int run(){
frequencyOne = new Integer((int)(Math.random() * 5000 + 50));
frequencyTwo = new Integer((int)(Math.random() * 5000 + 50));
return this.dif;
}
public int freqDif(){
return this.dif;
}
public void playQuiz(){
one.play(one.note(frequencyOne, 2, 15));//note(frequency, duration, volume)
two.play(two.note(frequencyTwo, 2, 15));
}
}
And here is the class where the quiz class is used:
public class Action implements ActionListener{
Quiz one = new Quiz();
public void actionPerformed (ActionEvent e){
if(e.getSource() == playSoundButton)
{
if(answerResponse.getText().compareTo("Correct!") == 0 || answerResponse.getText().compareTo("Play and Listen...") == 0)
{
one.run();
one.playQuiz();
}
else
{
one.playQuiz();
}
}
if(e.getSource() == submitButton)
{
String responseText = new String(responseField.getText());
if(responseText !=null && !"".equals(responseText)){
try{
Integer responseNumber = Integer.parseInt(responseText);
if(responseNumber == one.freqDif())
{
answerResponse.setText("Correct!");
answerResponse.setVisible(true);
}
else
{
answerResponse.setText("Wrong Answer. The difference is " + one.freqDif() + " hertz.");
answerResponse.setVisible(true);
}
}catch(NumberFormatException f){
f.printStackTrace(System.out);
}
}
}
}
}
private int dif = new Integer(Math.abs(frequencyTwo - frequencyOne));
This is calculated when the variable is created, not when you use the variable. You need to do the calculation after assigning the variables.
There are several issues with your code:
As others have mentioned, the line
private int dif = new Integer(Math.abs(frequencyTwo - frequencyOne));
creates a variable and assigns a value calculated from two other variables. The values of the other variables at the time of creation are used. You need to recalculate every time the values of those two variables changes. This does not happen automatically for you.
new Integer(...) creates an Integer object. When you subsequently assign this object to an int variable, the value is taken out of the object. This adds some unnecessary memory and run-time over head to your code. Instead, you should assign directly to your variables. For example,
frequencyOne = (int)(Math.random() * 5000 + 50);