Basically, I want to create Counter objects, all they have to do is hold number values. And in my resetCounters method, I would like to reset each object's values. This is probably very easy, but I'm a newb.
public class Counter
{
Random number = new Random();
Counter()
{
Random number = new Random();
}
public Random getNumber()
{
return number;
}
public void setNumber(Random number)
{
this.number = number;
}
public static void main(String[] args)
{
Counter counter1 = new Counter();
Counter counter2 = new Counter();
Counter counter3 = new Counter();
Counter counter4 = new Counter();
Counter counter5 = new Counter();
}
public static void resetCounters()
{
}
}
First option: Memorize each instance of Counter.
Collect each instance of Counter in some static collection.
To reset all, simply iterate over all items in the collection.
But strong references are too strong for this -- make sure it's a collection of weak references.
Remarks:
Using weak references will avoid the issue that the Counter objects exist indefinitely only because of their reference from within the static collection. Objects that are referred to only by weak references are eventually collected by the garbage collector.
The collection of every instance can be achieved by declaring the Counter constructor private and allowing only construction through a static member function which will also do the registration. (Or use some other incarnation of the Factory pattern.) I believe a factory is the way to go here, since each construction of an object has to carry out also a side effect. But perhaps it will make do to have the Counter constructor register this with the static collection.
Second option: Generation counter
Keep a static generation counter of type long, and also a copy of this counter in each instance. When resetting all counters, just increase the static generation counter. The getNumber() method will then check the static generation counter against its own copy and reset the counter if the static generation counter has changed.
(I don't really know the "official" name for this trick. How to zero out array in O(1)?)
Since we have no idea what the context is, we can't narrow down the specific thing you should do is, but the options that occur to me immediately are...
1: If the counters have distinct meanings beyond "counter1, counter2, counter3," then they could be static class variables (with more useful names).
public class Counter {
static Counter counter1 = new Counter();
...
public void resetCounters() {
counter1.clear();
counter2.clear();
...
}
}
2: If you just want several distinct counters, and they have no particular meaning by themselves, and you know that there will only ever be five of them, then you should use an array:
public class Counter {
public static void main(String[] args) {
Counter[] counters = {new Counter(), new Counter(), new Counter(), new Counter(), new Counter()};
...
}
static void resetCounters(Counter[] counters) {
for (Counter c : counters) {
c.reset();
}
}
}
Or, if you're planning to have an arbitrary number of them, you might try one of the fancier factory patterns. It really depends on what the context is, what you're actually trying to do, and what the point of the exercise is.
Since you're working with a large number of objects, you would be well served placing them in some sort of collection, like an ArrayList.
List<Counter> counters = new ArrayList<Counter>();
Insert all of your counters into there using the .add() method. Then, you can author your resetCounters() method in this manner:
public static void resetCounters(List<Counter> counters) {
for(Counter c: counters) {
// perform some action to reset the counters, as described by you
}
}
1. First of all there is not need to Initialize a Random nos as an instance variable,just have a Object Reference Varaible, as you are already initializing it in the Constructor.
eg:
Random number;
2. Create an ArrayList and store all the Counter objects.
ArrayList<Counter> arr = new ArrayList<Counter>();
3. Add each counter object in to the ArrayList.
4. Make reset function Non-static..there is no need for it to be static.
5. Iterate and reset...
for (Counter c : arr){
c.reset();
}
6. In reset() do the following..
public void reset(){
this.number = 0;
}
The easiest and elegant way of achieving what you want is keeping a reference to all created objects somewhere, in a factory for example and resetting them when needed.
public class CounterFactory{
private List<Counter> counters = new ArrayList<Counter>();
public Counter createCounter(){
Counter c = new Counter();
counters.add(c);
return c;
}
public void resetCounters(){
for(Counter c : counters) c.setNumber(new Random());
}
}
And in the main method, use it this way:
public static void main(String[] args)
{
CounterFactory f = new CounterFactory();
Counter counter1 = f.createCounter();
Counter counter2 = f.createCounter();
Counter counter3 = f.createCounter();
Counter counter4 = f.createCounter();
Counter counter5 = f.createCounter();
// Reset all counters
f.resetCounters();
}
Related
I'm new to multithreading in general, so I still don't fully understand it. I don't get why my code is having issues. I'm trying to populate an ArrayList with the first 1000 numbers, and then sum all of them using three threads.
public class Tst extends Thread {
private static int sum = 0;
private final int MOD = 3;
private final int compare;
private static final int LIMIT = 1000;
private static ArrayList<Integer> list = new ArrayList<Integer>();
public Tst(int compare){
this.compare=compare;
}
public synchronized void populate() throws InterruptedException{
for(int i=0; i<=Tst.LIMIT; i++){
if (i%this.MOD == this.compare){
list.add(i);
}
}
}
public synchronized void sum() throws InterruptedException{
for (Integer ger : list){
if (ger%MOD == this.compare){
sum+=ger;
}
}
}
#Override
public void run(){
try {
populate();
sum();
System.out.println(sum);
} catch (InterruptedException ex) {
Logger.getLogger(Tst.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
Tst tst1 = new Tst(0);
tst1.start();
Tst tst2 = new Tst(1);
tst2.start();
Tst tst3 = new Tst(2);
tst3.start();
}
}
I expected it to print "500.500", but instead it prints this:
162241
328741
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
at tst.Tst.sum(Tst.java:38)
at tst.Tst.run(Tst.java:50)
BUILD SUCCESSFUL (total time: 2 seconds)
The problem is happening because your methods are synchronized in "object level", I mean, the monitor lock it uses is of a particular object (tst1,tst2,tst3). In other words, each synchronized method is using a different lock.
Change your synchronized methods to static as a first step to fix it.
while run of tst1 is counting the sum in for-each then run of tst2 might increasing the size of list. So its throwing concurrent modification exception. Using a join can help.
public static void main(String[] args) {
Tst tst1 = new Tst(0);
tst1.start();
tst1.join()
Tst tst2 = new Tst(1);
tst2.start();
tst1.join()
Tst tst3 = new Tst(2);
tst3.start();
}
You misunderstood the semantic of synchronized method, each one uses different lock object in your case, do it this way:
class SynchList {
private int sum = 0;
private final int MOD = 3;
private int compare;
private final int LIMIT = 1000;
private ArrayList<Integer> list = new ArrayList<Integer>();
public synchronized void populate( int compare) throws InterruptedException{
for(int i=0; i<=LIMIT; i++){
if (i%this.MOD == compare){
list.add(i);
}
}
}
public synchronized void sum( int compare ) throws InterruptedException{
for (Integer ger : list){
if (ger%MOD == compare){
sum+=ger;
}
System.out.println( sum );
}
}
}
class Tst extends Thread {
int compare;
SynchList synchList;
public Tst(int compare, SynchList synchList)
{
this.compare= compare;
this.synchList = synchList;
}
#Override
public void run(){
try {
synchList.populate( compare );
synchList.sum( compare );
} catch (InterruptedException ex) {
Logger.getLogger(Tst.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class Main
{
public static void main(String[] args) {
SynchList synchList = new SynchList();
Tst tst1 = new Tst( 0 , synchList );
tst1.start();
Tst tst2 = new Tst( 1, synchList );
tst2.start();
Tst tst3 = new Tst( 2, synchList );
tst3.start();
}
}
Your use of synchronized methods isn't doing what you think it's doing. The way your code is written, the methods "sum" and "populate" are protected
from running at the same time, but only on the same thread instance. That means calls to "sum" and "populate" for a single Tst object will happen one at a time,
but simultaneous calls to "sum" on different object instances will be allowed to happen concurrently.
Using synchronized on a method is equivalent to writing a method that is wrapped
with synchronized(this) { ... } around the entire method body. With three different instances created – tst1, tst2, and tst3 – this form of synchronization
doesn't guard across object instances. Instead, it guarantees that only one of populate or sum will be running at a time on a single object; any other calls to one of
those methods (on the same object instance) will wait until the prior one finishes.
Take a look at 8.4.3.6. synchronized Methods in the Java Language Specification
for more detail.
Your use of static might also not be doing what you think it's doing. Your code also shares things across all instances of the Tst thread class – namely, sum and list. Because these are defined as static,
there will be a one sum and one list. There is no thread safety in your code to guard against concurrent changes to either of those.
For example, as threads are updating
"sum" (with the line: sum+=ger), the results will be non-deterministic. That is, you will likely see different results every time you run it.
Another example of unexpected behavior with multiple threads and a single static variable is list – that will grow over time which can result in concurrency issues. The Javadoc says:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
Modifications include adding values as well as growing the backing array store. Without specifying a starting size – new ArrayList() – it will default to 10 or possibly some other relatively small number depending on which JVM version you're using. Once one thread tries to add an item that exceeds the ArrayList's capacity, it will trigger an automatic resize.
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
In my program, I want to create multiple threads in one of the methods where each thread has to run a specific method with a given input. Using Runnable, I have written this snippet.
class myClass {
public myClass() { }
public void doProcess() {
List< String >[] ls;
ls = new List[2]; // two lists in one array
ls[0].add("1"); ls[0].add("2"); ls[0].add("3");
ls[1].add("4"); ls[1].add("5"); ls[1].add("6");
// create two threads
Runnable[] t = new Runnable[2];
for (int i = 0; i < 2; i++) {
t[ i ] = new Runnable() {
public void run() {
pleasePrint( ls[i] );
}
};
new Thread( t[i] ).start();
}
}
void pleasePrint( List< String > ss )
{
for (int i = 0; i < ss.size(); i++) {
System.out.print(ss.get(i)); // print the elements of one list
}
}
}
public class Threadtest {
public static void main(String[] args) {
myClass mc = new myClass();
mc.doProcess();
}
}
Please note, my big code looks like this. I mean in one method, doProcess(), I create an array of lists and put items in it. Then I want to create threads and pass each list to a method. It is possible to define the array and lists as private class members. But, I want to do that in this way.
Everything seems to be normal, however, I get this error at calling pleasePrint():
error: local variables referenced from an inner class must be final or effectively final
pleasePrint( ls[i] );
How can I fix that?
The reason you are getting this error is straightforward and clearly mentioned - local variables referenced from an inner class must be final or effectively final. This is, in turn, because, the language specification says so.
Quoting Guy Steele here:
Actually, the prototype implementation did allow non-final variables
to be referenced from within inner classes. There was an outcry from
users, complaining that they did not want this! The reason was interesting: in order to support such variables, it was necessary to
heap-allocate them, and (at that time, at least) the average Java
programmer was still pretty skittish about heap allocation and garbage
collection and all that. They disapproved of the language performing
heap allocation "under the table" when there was no occurrence of the
"new" keyword in sight.
As far as your implementation goes, instead of using an array of list, I'd rather use a list of lists.
private final List<List<String>> mainList = new ArrayList<>();
You can create new lists and insert them into the main list in the constructor depending on the number of lists you want.
public ListOfLists(int noOfLists) {
this.noOfLists = noOfLists;
for (int i = 0; i < noOfLists; i++) {
mainList.add(new ArrayList<>());
}
}
You can then change your doProcess() method as follows:
public void doProcess() {
for (int i = 0; i < noOfLists; i++) {
final int index = i;
// Using Lambda Expression as it is much cleaner
new Thread(() -> {
System.out.println(Thread.currentThread().getName());
pleasePrint(mainList.get(index)); // Pass each list for printing
}).start();
}
}
Note: I used an instance variable named noOfLists to (as the name suggests) store the number of lists I need. Something as follows:
private final int noOfLists;
To populate the list, you could do:
mainList.get(0).add("1");
mainList.get(0).add("2");
mainList.get(0).add("3");
mainList.get(1).add("4");
mainList.get(1).add("5");
mainList.get(1).add("6");
// And so on...
And you'll get the output something as:
Thread-0
1
2
3
Thread-1
4
5
6
Hope this helps :)
First to that, you will get a NullPointerException here:
ls[0].add("1"); ls[0].add("2"); ls[0].add("3");
ls[1].add("4"); ls[1].add("5"); ls[1].add("6");
Before, yo must instantiate the lists:
ls[0] = new ArrayList<>();
ls[1] = new ArrayList<>();
About the compiler error, try to define the array as final. Change:
List< String >[] ls;
ls = new List[2]; // two lists in one array
By:
final List< String >[] ls = new List[2]; // two lists in one array
This is because you can't access to non-final (or effectively final) variables from a local class.
'ls' is effectively final but probably, since you have defined it in two lines, the compiler is not able to notice that.
I'm looking for a better way to organize my class.
Right now my code looks like this:
mainMethod:
-number1 input
-call method1 with number1 als value
method1:
-do "stuff" with input
-call method2 with new "stuff" as value
method2:
-do stuff
-call method3
etc...
So i start with user input in my main method and my whole class works like domino, the first method needs to be called to run the next method.
I would rather have method1 return a value and save it in some global variable in my class which can be used by method2 and so on.
Here is my Code with exactly this problem: (it calculates sqrt)
package wurzel;
import java.util.Scanner;
import wurzel.Fraction;
public class wurzel {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Eingabe:");
int in = s.nextInt();
s.close();
bisection(in);
}
private static int bisection(int N){
int counter = 0;
for(int i = 0; i < N;i++){
if((counter*counter) > N){
counter--;
break;
}
else if(counter*counter == N){
break;
}
else counter++;
}
calculateSequence(counter,N);
return counter;
}
static int[] calculateSequence(int vKomma, int look){
int m = 0;
int d = 1;
int a = vKomma;
int[] intarr = new int[4];
intarr[0] = vKomma;
for(int i = 1; i <= intarr.length; i++){
if(i == intarr.length )
break;
else{
m = (d*a) - m;
d = (look - (m*m)) / d;
a = (vKomma + m) / d;
intarr[i] = a;
}
}
calculateApproximation(intarr);
return intarr;
}
static double calculateApproximation(int[] sequence ){
Fraction result = new Fraction((sequence.length)-1);
for(int dcounter = sequence.length; dcounter > 0; dcounter--){
result = result.reciprocal().add(sequence[dcounter-1]);
}
System.out.println("Approximation als double: " +result.doubleValue());
System.out.println("Approximation als Bruch: " +result);
return result.doubleValue();
}
}
You should also seperate code into different classes. E.g. have a generic MathHelper class which has these methods in it.
This helps keep code seperate and easy to read.
You mentioned that you wanted to store some data in a global variable for the class as a whole. The way to do this is by making the class use instance methods rather than class methods. With class methods, you have to use class variables. But, when you use instance methods, you can define instance variables which can be accessed by any method within the class.
To do this, change all your methods (apart from main()) by removing the keyword static from each method. Then, define the instance variable that is global for the class. e.g. if your global variable is of type int then it would be:
private int myInstanceVariable;
This instance variable, or global variable, can be accessed by a getter and setter.
It is quite normal methods to call each other and to form long chains of calls.
So I would not worry about that. Actually in real world, in enterprise code,
you have call stack going through tens of calls. So I think global variables would
be worse practice compared to what you did.
In a interview I was asked to wrtie a method which will generate unique 5 digit random number everytime when it is called.For ex: if I call the method and get 22222 then in next call i should not get 22222.
I wrote a code as below:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class RandomNumberGen {
private static ArrayList arr=new ArrayList();
private static int k=-1;
public RandomNumberGen(){
for (int i=10000;i<99999;i++){
arr.add(i);
}
Collections.shuffle(arr);
}
public static void main(String[] args) {
for(int m=0;m<10;m++){
try {
System.out.println(new RandomNumberGen().randomNumbermethod());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public Integer randomNumbermethod() throws Exception{
k++;
if(k>=arr.size()){
throw new Exception("No more number available");
}else return (Integer) arr.get(k);
}
}
Answer got accepted but I was asked to avoid memory wastage now.
My question is here as you can see I am using only 10 numbers.So rest of the space occupied by arraylist is a memory-wastage.Is there a way I can achieve same thing without using extra memory.
What I mean is there someway using which unique number can be generated on each call so that this much memory do not get wasted.
private static int number = 10000;
public int getNextUniqueRandomNumber() {
return number++;
}
Implications:
In order to not to return the same value twice, you need to track which numbers you've already generated. This can be very memory consuming.
You eventually run out of numbers. Instead of keeping on searching for an unused random number, you can track how many numbers you've returned (or how many are still available) and recognize if you ran out of numbers.
The generated numbers could be tracked in a collection (Set). This means having an overhead of 32bit per number (when tracking available or generated numbers) plus the collection overhead. Another possibility is to use a boolean-array and mark which slots have been used. Again, this is an overhead, as booleans usually are stored as 32bit value.
But there's a cheaper way to store booleans: as packed bits in an integer. That's what java.util.BitSet does, so each boolean will occupy one bit.
Solution with BitSet and tracking how many numbers are available:
public class RandomNumbers {
private final Random random = new Random();
private final BitSet used = new BitSet();
private final int min = 10000;
private final int max = 99999;
private final int numbersAvailable = max - min + 1;
public static void main (String[] args) {
RandomNumbers randomNumbers = new RandomNumbers();
for (int i = 0; i < 100; i++) {
System.out.println(randomNumbers.nextRandom());
}
}
public int nextRandom () throws NoSuchElementException {
while (numbersAvailable > 0) {
int rnd = min + random.nextInt(max - min + 1);
if (!used.get(rnd)) {
used.set(rnd);
numbersAvailable--;
return rnd;
}
}
throw new NoSuchElementException();
}
}
Just
(int)(Math.random()*89999)+10000
After edit: (just not understood before edit) - you can put generated number in HashSet and after random just check if set contains new number (it will go very slow if you use it many times, but I think this is a good solution if you don't need a lot of numbers.
From my comment: After exceding about 50% of numbers I would create a collection of remaining numbers to pick, same as yours, but you should document in class, that it can freeze for a moment after 50% results usage and give ability to set this factor to client.
Maybe ther is a better way, depending of "how much randomness" must be in generated numbers (for example mathematical approach to sequence generator)
Seems pretty straightforward. A much simpler solution with less memory usage is to just create a set that will hold all the numbers you want like this:
Random random = new Random();
Set<Integer> randomNumbers = new HashSet<Integer>(10);
while(randomNumbers.size() < 10)
randomNumbers.add( new Integer(random.nextInt(89999) + 10000) );
And to view them all:
for(Integer randomNumber : randomNumbers){
System.out.println(randomNumber);
}
This will guarantee uniqueness to the properties of a set and greatly improve your memory usage.
Your method would indeed be ideal to create a large number of unique values, however if you are only creating a small number of unique values it can be more efficient to simply keep track of the used values to garantee uniqueness
import java.util.Collection;
import java.util.HashSet;
import java.util.Random;
public class UniqueRandom {
static Random rnd=new Random();
public static void main(String args[]){
Collection<Integer> alreadyChosen = new HashSet<Integer>();
for(int i=0;i<10;i++){
System.out.println(getNextUniqueRandom (alreadyChosen));
}
}
public static int getNextUniqueRandom(Collection<Integer> alreadyChosen){
if (alreadyChosen.size()==90000){ //hardcoded 5 figure numbers, consider making a variable
throw new RuntimeException("All 5 figure IDs used");
}
boolean unique=false;
int value=0;
while(unique==false){
value=rnd.nextInt(90000)+10000;
unique=!alreadyChosen.contains(value);
}
alreadyChosen.add(value);
return value;
}
}
This method is highly efficient when only a small proportion of the available range is required but becomes slower and slower as collisions become more common. The exact implementation you should choose is highly dependant upon how many values you need to get.
Notes to consider
As already stated this will get very very slow as more values are
chosen, should be made clear to end user, or even better; change algorithm after so many calls
I'm new to using OOP, I typically just put all my code in a single class and use methods. But I want to maintain state information and think classes are the best fit but I'm having trouble wrapping my head around it.
Say I have a list of items and I want to stop when the total sum of all previous items in the list equals X(in this case 10 so it takes item 1 + 2, then 2+3.etc..until it hits the threshold 10), I can use a method to calculate it but it involves me doing the entire process all over again when all I really need to do is increment by the last item and then see if my data exceeds the threshold. Here's my code so far but I know its not good because although it works its really just using the class as an independent method and recalculating on every loop. My goal is to,using this structure, reduce loops if not necessary to check thresholds.
Any suggestions?
Code:
public class LearningClassesCounter {
public static void main(String[] args) {
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data(current_location));
for (int i =0; i<100; i++){
if (checker.check_data(current_location) == false) {
break;
}
data_list[current_location] = (list[current_location]+1); //this is just a random function, it could be any math function I just put it in here to show that some work is being done.
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
}
class Counter {
private int[] data_list;
private int total_so_far;
// create a new counter with the given parameters
public Counter(int[] data_list) {
this.data_list = data_list;
this.total_so_far = 0;
}
public boolean check_data(int current_location) {
// TODO Auto-generated method stub
int total_so_far = 0;
//System.out.println(total_so_far);
for (int item : data_list) {
total_so_far = item + total_so_far;
if (total_so_far >= 10) {
break;
}
}
if (total_so_far>=10) {
return false;
} else {
return true;
}
}
}
I don't need anyone to fix my code or anything(I want to do it myself, the code is just to give an idea of what I'm doing). I'm more interested in the flaw in my logic and maybe a way for me to better think about designing classes so I can apply them to my own situations better.
So the solution is that you do not update the data_list directly. Instead have a setter method in the Counter class that takes the index and value to update. It updates the value in the array and also updates a count value.
Something like this:
class Counter{
private final int[] list;
private count = 0;
private final maxCount = 10;
public Counter(int[] list){
this.list = list;
}
public boolean updateValueAndCheckPastMax(int index, int value){
list[index] = value;
count += value;
return count >= maxCount;
}
}
You are way over thinking this, and a counter class is not really necessary in this case.
I'm also interested as to why you'd be doing this line:
data_list[current_location] = (list[current_location]+1);
Do you want your data_list to be the same as list, but each value is incremented by 1?
If you are merely trying to return a sub-array of the values that are < 10, i would suggest just doing this in a for loop, and using an int as a counter.