I want to generate a list of unique random numbers from a given input range using threads in Java. For example, given a range of 1-4, I would run 4 threads and each thread would generate a random number such that no two threads would produce the same value twice. I presume I need to implement some synchronization or something? I've tried using Join() but it doesn't seem to work.
My constructor uses input values to populate an array list with a given range. In the run method, I generate a random value (from the same range) and check if it's in the list. If it is, I remove it from the list and print the value. The idea is that when another thread comes in, it can't generate that same value again.
Here is what I have so far:
public class Main {
public static void main(String[] args) {
randomThreadGen randomRange = new randomThreadGen(1, 2);
Thread thread1 = new Thread(randomRange);
Thread thread2 = new Thread(randomRange);
thread1.start();
try {
thread1.join();
} catch (InterruptedException e) {
}
thread2.start();
}
}
And this:
public class randomThreadGen implements Runnable {
private int lowerBound;
private int upperBound;
private final ArrayList<Integer> List = new ArrayList<Integer>();
public randomThreadGen(int lowerb, int upperb) {
this.lowerBound = lowerb;
this.upperBound = upperb;
for (int i = lowerb; i < upperb + 1; i++) { // populate list with values based on lower and upperbounds specified from main
List.add(i);
}
}
#Override
public void run() {
// generate random value
// check if in list. If in list, remove it
// print value
// otherwise try again
int val = ThreadLocalRandom.current().nextInt(lowerBound, upperBound+1); // generate random value based on lower and upper bound inputs from main
while(true){
if(List.contains(val)){
List.remove(new Integer(val));
System.out.println("Random value for " + Thread.currentThread().getName() + " " + val);
System.out.println("List values: " + List);
}
break;
}
}
}'''
This test case with a low range is to make testing easy. Sometimes it works, and Thread0 will generate a different value to Thread01 (1 and 2 or 2 and 1 for example). But sometimes it doesn't (seemingly they generate the same value, in which case my code only prints one value) For example, "Thread02 1" and nothing else.
Any ideas? Is there another way to do this other than join()?
It's quite an easy task. Just use a concurrent hashmap to prevent duplicates. Make sure to declare boundary int and the hashmap as final. Thread.join is needed to guarantee that the results will be printed after all threads have complete their work. There are other effective techniques to replace join but they are not for novices.
Try this:
import java.util.concurrent.ThreadLocalRandom;
import java.util.*;
import java.util.concurrent.*;
public class Main {
final static int low = 0;
final static int up = 5;
final static Set < Integer > inthashmap = ConcurrentHashMap.newKeySet();
// threadhashmap is needed to track down all threads generating ints
final static Set < Thread > threadhashmap = ConcurrentHashMap.newKeySet();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < up - low + 1; i++) {
Thread t = new Thread() {
public void run() {
int randomNum;
try {
randomNum = ThreadLocalRandom.current().nextInt(low, up + 1);
inthashmap.add(randomNum);
System.out.println("A new random int generated : " + randomNum);
} finally {
}
}
};
threadhashmap.add(t);
t.start();
}
//by iterating through all threads in threadhashmap
// and joining them we guarantee that all threads were completed
// before we print the results of work of those threads (i.e. ints)
Iterator<Thread> iterator = threadhashmap.iterator();
while (iterator.hasNext())
iterator.next().join();
System.out.println("Unique ints from hashmap:");
inthashmap.forEach(System.out::println);
}
}
Output:
A new random int generated : 2
A new random int generated : 3
A new random int generated : 3
A new random int generated : 0
A new random int generated : 0
A new random int generated : 2
Unique ints from hashmap:
0
2
3
Related
Like the caption said the method "scanInput1" runs two times in a row when it should only run once. Then the method "arrayskapare" runs as intended but after that. instead of running the method "medelvarde" is jumps back and runs "scanInput1" again and again and again
import java.util.*;
class Heltalshanterare{
private static String scanInput1(){
System.out.print("Skriv in antal heltal: ");
Scanner scr = new Scanner(System.in);
String antalHeltal = scr.next();
try {
Integer.parseInt(antalHeltal);
}
catch (NumberFormatException e) {
System.out.println("Ogilitigt värde");
scanInput1();
}
return antalHeltal;
}
private static List<Integer> arrayskapare() {
int antalangivnatal = Integer.parseInt(scanInput1());
int noll = 1;
int heltal = 0;
String tal1 = "";
Scanner tal = new Scanner(System.in);
List<Integer> list = new ArrayList<>();
while (noll <= antalangivnatal) {
noll++;
heltal++;
System.out.print("ange heltal " + heltal + ": ");
tal1 = tal.next();
try {
int num = Integer.parseInt(tal1);
list.add(num);
} catch (NumberFormatException e) {
System.out.println("Ogiltigt värde");
noll--;
heltal--;
}
}
return list;
}
public static int medelvarde(){
int antalsiffror = arrayskapare().size();
int sum = 0;
for (int i : arrayskapare()){sum += i;}
int medelvärde = sum / antalsiffror;
System.out.println("medelvärdet av dina tal är " + medelvärde);
return medelvarde();
}
public static void main(String [] args){
scanInput1();
arrayskapare();
medelvarde();
}
}
Im sorry that the code is so long but I have been struggling with this for too long and I really need some help.
Your main method is calling each method just once, which is what you need. But it's not actually holding onto any of the values being returned. So the number of heltal (integers in English) is captured from the user but then never actually stored anywhere. And later an array of numbers is captured but not stored anywhere.
Your second, bigger problem is that your methods are then calling the earlier methods all over again. So instead of asking the user to type in the data just once, you're forcing them to answer the exact same questions multiple times.
A much tidier approach is to alter your methods so that they take the required data as a parameter. Which means your arrayskapare (array producer) method should take the antalHeltal (number of integers) value as a parameter, and then it won't need to call the scanInput1 method again. Same thing can be done for your medelvarde (mean value) method: have it take the array as a method parameter, so that it won't need to call arrayskapare.
With those changes your main method can simply look like this:
public static void main(String [] args){
int antalHeltal = scanInput1();
List<Integer> heltalArray = arrayskapare(antalHeltal);
int medelvardet = medelvarde(heltalArray);
System.out.println("Medelvärdet är " + medelvardet);
}
Now each method just gets called once and the data captured from the user gets stored into variables and passed along the river of methods until the final result is reached.
This question already has answers here:
How to wait for a number of threads to complete?
(14 answers)
Closed 3 years ago.
I am trying to populate a static array using multiple threads. The suggested usage of join() in https://stackoverflow.com/a/1492077/10418317 seems to be imposing a specific order on the threads. I want them to run in parallel if they can so as to speed up the whole process
Assigment
public class Assigment {
public static int minPrime;
public static int maxPrime;
public static int[] masterMin = new int[10];
public static int[] masterMax = new int[10];
public static void main(String[] args) {
// TODO code application logic here
for(int i = 1; i < 11;i++){
Thread thread = new Thread(new NumGenerator(i));
thread.start();
System.out.println("Thread " + i + " generating nums");
}
Arrays.sort(masterMin);
Arrays.sort(masterMax);
minPrime = masterMin[0];
maxPrime = masterMax[9];
System.out.println("<------------------------------>");
System.out.println("Max Prime is " + maxPrime);
System.out.println("Min Prime is " + minPrime);
}
}
NumGenerator
public class NumGenerator implements Runnable {
int[] numbers;
int thrnum;
public NumGenerator(int thrnum){
this.thrnum = thrnum;
}
#Override
public void run(){
Random rand = new Random();
numbers = new int[3000];
for(int i = 0; i<3000; i++){
numbers[i] = rand.nextInt(899999)+1;
}
Searcher searcher = new Searcher(numbers);
Assigment.masterMax[thrnum-1] = searcher.max;
Assigment.masterMin[thrnum-1] = searcher.min;
}
I am trying to sort the array after every thread has completed inputting into it and then print out the first and the last i.e the smallest and the largest values.The problem is that the arrays masterMin and masterMax seem to be still having all zero entries after the supposed population through Assigment.masterMin[thrnum-1] = searcher.min; Searcher is another class which is actually giving me non-zero values for search.max and search.max as expected.
As pointed by #jhamon threads have not completed. But the approach give by #Sree is not ideal as shutting down a Executor just for the sake of waiting for the threads to complete is not the best of the approaches. You can try the following :
ExecutorService executor = Executors.newFixedThreadPool( 10 );
List<Callable<Object>> calls = new ArrayList<>();
for(int i = 1; i < 11;i++){
calls.add(Executors.callable(new NumGenerator(i)));
System.out.println("Thread " + i + " generating nums");
}
List<Future<Object>> futures = svc.invokeAll(calls);
invokeAll() will not return until all the tasks are completed (either by failing or completing successful execution).
#jhamon has already explained the reason. (That the threads have not completed)
How to solve it? Convert the part where you are starting threads to something like this using ExecutorService.
ExecutorService svc = Executors.newFixedThreadPool( 10 );
for(int i = 1; i < 11;i++){
//Thread thread = new Thread(new NumGenerator(i));
//thread.start();
svc.submit( () -> new NumGenerator( i ) );
System.out.println("Thread " + i + " generating nums");
}
svc.shutdown();
svc.awaitTermination( 2, TimeUnit.MINUTES );
//Now, print the values.
I am trying to get a grasp on synchronizing threads, but I don't understand the problem I'm encountering.
Can someone please help me diagnose this or, even better, explain how I can diagnose this for myself?
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
public class Controller {
public static void main(String[] args) {
int numThreads = 0;
List<Thread> threads = new ArrayList<>();
if (args.length > 0) {
numThreads = Integer.parseInt(args[0]);
}
else {
System.out.println("No arguments");
System.exit(1);
}
CyclicBarrier barrier = new CyclicBarrier(numThreads);
int arr[][] = new int[10][10];
for (int i = 0; i < numThreads; i++) {
Thread newThread = new Thread(new ThreadableClass(barrier, arr));
threads.add(newThread);
}
for (Thread thread : threads) {
thread.start();
}
}
}
There is a main method (above) which accepts the number of threads I want as a command line argument. And there is a work-flow (below) which I am aiming to have increment all elements in a 2D array and print the array before the next thread has its chance to do the same:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class ThreadableClass implements Runnable {
private CyclicBarrier barrier;
private int arr[][];
public ThreadableClass(CyclicBarrier barrier, int[][] arr) {
this.barrier = barrier;
this.arr = arr;
}
#Override
public void run() {
long threadId = Thread.currentThread().getId();
System.out.println(threadId + " Starting");
for (int i = 0; i < 10; i++) {
changeArray();
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
private synchronized void changeArray() {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
arr[i][j]++;
}
}
printArray();
}
private synchronized void printArray() {
System.out.println(Thread.currentThread().getId() + " is printing: ");
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}
Imagining the size of the array is 2x2, the expected output would look something like this:
1 1
1 1
2 2
2 2
3 3
3 3
4 4
4 4
...
...
(10 * numThreads)-1 (10 * numThreads)-1
(10 * numThreads)-1 (10 * numThreads)-1
(10 * numThreads) (10 * numThreads)
(10 * numThreads) (10 * numThreads)
Instead, all threads increment the array, and begin printing over one another.
There is nothing surprising about the result. You create n threads. You tell all threads to start. Each threads run() starts with:
long threadId = Thread.currentThread().getId();
System.out.println(threadId + " Starting");
...changeArray();
going to change that shared array. After writing to the array, you try to sync (on that barrier). Its too late then!
The point is: you have 10 different ThreadableClass instances. Each one is operating on its own! The synchronized key word ... simply doesn't provide any protection here!
Because: synchronized prevents two different threads calling the same method on the same object. But when you have multiple objects, and your threads are calling that method on those different objects, than there is no locking! What your code does boils down to:
threadA to call changeArray() .. on itself
threadB to call changeArray() .. on itself
threadC to call changeArray() .. on itself
...
In other words: you give n threads access to that shared array. But then you allow those n threads to enter changeArray() at the same time.
One simple fix; change
private synchronized void changeArray() {
to
private void changeArray() {
synchronized(arr) {
In other words: make sure that the n threads have to lock on the same monitor; in that case the shared array.
Alternatively: instead of making changeArray() a method in that ThreadableClass ... create a class
ArrayUpdater {
int arr[] to update
synchronized changeArray() ...
Then create one instance of that class; and give that same instance to each of your threads. Now the sync'ed method will prevent multiple threads to enter!
Because you are providing new instance for each theard using new ThreadableClass(barrier, arr), basically, all the theadrs are using different ThreadableClass objects, so your code synchronized methods run parallely, so you need to use a single ThreadableClass object as shown below:
ThreadableClass threadableClass= new ThreadableClass(barrier, arr);
for (int i = 0; i < numThreads; i++) {
Thread newThread = new Thread(threadableClass);
threads.add(newThread);
}
The important point is synchronization is all about providing access (i.e., key) to an object for a single thread at a time. If you are using a different object for each thread, threads don't wait for the key because each thread has got its own key (like in your example).
This is a Java Program to Find The Number with Largest Divisors from 1-500000.
public class Medium2 {
static int count1 = 1;
static int count2 = 1;
static int big_count = 0;
static int big = 0;
Main method
public static void main(String[] args) {
Runnable runnable1 = new Runnable() {
public void run() {
The implementation goes here
for (int num = 1; num <= 500000; num++) {
for (int i = 2; i <= num; i++) {
if (num % i == 0) { //Actual Logic
count1++;
}
}
if (count1 > big_count) {
big_count = count1; //Number of Divisors
big = num; //Largest Number
}
count1 = 1;
}
}
};
And the thread execution
Thread thread1 = new Thread(runnable1); //Threads
Thread thread2 = new Thread(runnable1);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException ie) {
;
}
System.out.println("Biggest: " + big + "\nNumber of Divisors for " + big + " = " + big_count);
}
}
But it gives different answers every time. The actual answer is : 498960 and 200 Divisors
Concerning your goal, your implementation should probably have problems. Since big_count and big is common for both threads and don't have any protection when threads are trying to modify those, your program should create errors.
Other than that, you are also not utilizing 2 threads, since both threads are doing calculation from 1 to 500000.
Since your calculation logic seems ok, you should get your desired output when you try with single thread.
If you want it to do by two threads, you can easily try this. (just to verify, not the nicest way)
You should have big_count1, big1 and big_count2, big2. So that variables whose names end with '1' is only using by thread1 and variables whose names end with '2' is only using by thread2.
Assign thread1 to check from 1 to 250000 and thread2 to from 250001 to 500000.
After join() s, just compare big_count1 and big_count2, then you can deduce the final answer. :))
im pretty new to java stuff. At the moment i am trying to write a programm dealing with the birthday problem(wikipedia). I want to know how many people have to be asked for their day and month of birth until one is duplicate.
I wrote a class doing the "asking" with the following code:
public class Starter {
static ArrayList<Integer> peeps = new ArrayList<Integer>();
static boolean match = false;
static int counter = 0;
public static int doRand() {
int rand = (1 + (int) (Math.random() * ((365 - 1) + 1)));
return rand;
}
public static int start() {
do {
int buffer = 0;
buffer = doRand();
if (peeps.isEmpty()) {
peeps.add(doRand());
}
counter++;
for (int i = 0; i < peeps.size(); i++) {
if (peeps.get(i) == buffer) {
match = true;
}
}
peeps.add(buffer);
} while (match == false);
return counter;
}
}
This seems to work and produces numbers somewhat between 10 and 50.
But if I run this function from the following for-loop, I get really strange result:
public class BirtdayProblem {
public static void main(String[] args) {
for (int i=0;i< 1000;i++) {
System.out.println(Starter.start());
}
}
}
It produces an output of 1000 continous numbers...why?
If I run the function multiple times manually, i have never gotten any continous number...
Can someone explain that to me?
Example Output:
25
26
27
...
...
1016
1017
1018
1019
1020
1021
1022
1023
1024
Does not look ver yRandom to me...?
Starter.start() returns the static "counter" value which is incremented by 1 after every iteration in the for loop , hence the output shows the output in increments of 1 .
You are using static member variables for counter and match. That means they belong to the class and will not be reset between calls to start().
Since these variables are used only inside the start() method I suggest you put their declarations there as well.
public static int start() {
boolean match = false;
int counter = 0;
And remove the old declarations at the top.