Populating a static array using multiple threads [duplicate] - java

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.

Related

Easy way to generate unique random numbers (range) using threads? Java

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

This thread program shows me different answers every time

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. :))

Multi thread is slower than one [duplicate]

This question already has answers here:
Java: How to use Thread.join
(3 answers)
Closed 8 years ago.
I am writing application using multi threads to count number of char inside txt file.
File contains 10 000 000 chars. 10 000 rows and 1 000 columns.
EDITED
About first part of the question:
Prevoius questions was about threads, I used a thread.join(); in wrong way.
Second part:
Could you help me improve the performance and safety? Here is my code (Use of the Semaphore is required):
public class MultiThread implements Runnable {
HashMap<String, AtomicInteger> asciiMap = Maps.newHashMap();
LinkedList<String> asciiLines = ReadDataFromFile.lines;
Semaphore mutex = new Semaphore(1);
AtomicInteger i = new AtomicInteger(0);
int index;
#Override
public void run() {
long actual = 0;
try {
Calculate calculate = new Calculate();
long multiStart = System.currentTimeMillis();
Thread first = new Thread(calculate);
Thread second = new Thread(calculate);
Thread third = new Thread(calculate);
first.start();
second.start();
third.start();
first.join();
second.join();
third.join();
long multiEnd = System.currentTimeMillis();
actual = multiEnd - multiStart;
} catch (InterruptedException ex) {
Logger.getLogger(MultiThread.class.getName()).log(Level.SEVERE, null, ex);
}
int sum = 0;
for (Map.Entry<String, AtomicInteger> entry : asciiMap.entrySet()) {
System.out.println("Char: " + entry.getKey() + " , number: " + entry.getValue());
sum = sum + entry.getValue().get();
}
System.out.println("Time: " + actual);
}
int increment() {
try {
mutex.acquire();
index = i.incrementAndGet();
mutex.release();
} catch (InterruptedException ex) {
Logger.getLogger(MultiThread.class.getName()).log(Level.SEVERE, null, ex);
}
return index;
}
public class Calculate implements Runnable {
public Calculate() {
}
#Override
public void run() {
while (i.get() < asciiLines.size()) {
for (String oneCharacter : asciiLines.get(i.get()).split("")) {
if (asciiMap.containsKey(oneCharacter)) {
asciiMap.replace(oneCharacter, new AtomicInteger(asciiMap.get(oneCharacter).incrementAndGet()));
} else {
asciiMap.put(oneCharacter, new AtomicInteger(1));
}
}
i = new AtomicInteger(increment());
}
}
}
}
Every element inside LinkedList contains one row (1 000 chars).
Your code does absolutely no multithreading. Thread.join means wait until that thread has finished executing, then continue the current thread of execution. Right now, your code is executing each thread serially. You want to interleave your calls to start and join.
Thread first = new Thread(calculate);
Thread third = new Thread(calculate);
Thread second = new Thread(calculate);
first.start();
second.start();
third.start();
first.join();
second.join();
third.join();

Java ThreadPoolExecutor

I'm having big troubles understanding the Java ThreadPoolExecutor. For example, I want to calculate the squares of numbers 1-1000:
public static void main(String[] args) throws InterruptedException, ExecutionException {
Callable<ArrayList<Integer>> c = new squareCalculator(1000);
ExecutorService executor = Executors.newFixedThreadPool(5);
Future<ArrayList<Integer>> result = executor.submit(c);
for(Integer i: result.get()){
System.out.println(i);
}
}
And the
public class squareCalculator implements Callable<ArrayList<Integer>>{
private int i;
private int max;
private int threadID;
private static int id;
private ArrayList<Integer> squares;
public squareCalculator(int max){
this.max = max;
this.i = 1;
this.threadID = id;
id++;
squares = new ArrayList<Integer>();
}
public ArrayList<Integer> call() throws Exception {
while(i <= max){
squares.add(i*i);
System.out.println("Proccessed number " +i + " in thread "+this.threadID);
Thread.sleep(1);
i++;
}
return squares;
}
}
Now my problem is, that I only get one thread doing the calculations. I expected to get 5 threads.
If you want the Callable to run 5 times concurrently, you need to submit it 5 times.
You only submitted it once, and then ask for its result 5 times.
Javadoc of submit():
Submits a value-returning task for execution and returns a
Future representing the pending results of the task. The
Future's get method will return the task's result upon
successful completion.
You see that Javadoc for submit() uses the singular for "task", not "tasks".
The fix is easy: submit it multiple times:
Future<ArrayList<Integer>> result1 = executor.submit(c);
Future<ArrayList<Integer>> result2 = executor.submit(c);
Future<ArrayList<Integer>> result3 = executor.submit(c);
/// etc..
result1.get();
result2.get();
result3.get();
// etc..
The ExecutorService will use one thread to execute each Callable task that you submit. Therefore, if you want to have multiple threads calculating the squares, you have to submit multiple tasks, for example one task for each number. You would then get a Future<Integer> from each task, which you can store in a list and call get() on each one to get the results.
public class SquareCalculator implements Callable<Integer> {
private final int i;
public SquareCalculator(int i) {
this.i = i;
}
#Override
public Integer call() throws Exception {
System.out.println("Processing number " + i + " in thread " + Thread.currentThread().getName());
return i * i;
}
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Future<Integer>> futures = new ArrayList<>();
// Create a Callable for each number, submit it to the ExecutorService and store the Future
for (int i = 1; i <= 1000; i++) {
Callable<Integer> c = new SquareCalculator(i);
Future<Integer> future = executor.submit(c);
futures.add(future);
}
// Wait for the result of each Future
for (Future<Integer> future : futures) {
System.out.println(future.get());
}
executor.shutdown();
}
}
The output then looks something like this:
Processing number 2 in thread pool-1-thread-2
Processing number 1 in thread pool-1-thread-1
Processing number 6 in thread pool-1-thread-1
Processing number 7 in thread pool-1-thread-2
Processing number 8 in thread pool-1-thread-2
Processing number 9 in thread pool-1-thread-2
...
1
4
9
...
This is a funny problem to try to do in parallel because creating the result array (or list) runs in O(n) time because it gets initialized with zeros on creation.
public static void main(String[] args) throws InterruptedException {
final int chunks = Runtime.getRuntime().availableProcessors();
final int max = 1001;
ExecutorService executor = Executors.newFixedThreadPool(chunks);
final List<ArrayList<Long>> results = new ArrayList<>(chunks);
for (int i = 0; i < chunks; i++) {
final int start = i * max / chunks;
final int end = (i + 1) * max / chunks;
final ArrayList<Long> localResults = new ArrayList<>(0);
results.add(localResults);
executor.submit(new Runnable() {
#Override
public void run() {
// Reallocate enough space locally so it's done in parallel.
localResults.ensureCapacity(end - start);
for (int j = start; j < end; j++) {
localResults.add((long)j * (long)j);
}
}
});
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MICROSECONDS);
int i = 0;
for (List<Long> list : results) {
for (Long l : list) {
System.out.printf("%d: %d\n", i, l);
++i;
}
}
}
Overhead dealing with the wrapper classes will kill performance, here, so you should use something like Fastutil. Then, you could join them with something like Guava's Iterables.concat, only a List version that's compatible with Fastutil's LongList.
This might also make a good ForkJoinTask, but again, you'll need efficient logical (mapping, not copying; the reverse of List.sublist) List concatenation functions to realize a speedup.

Create ten instances of a class simultaneously using threads

I am trying to understand threads in Java. As an exercise, I created an Ice Cream class as follows.
public class ThreadIceCream {
private String flavor = "";
private String[] specialFlavors = { "Vanilla", "Chocolate", "Butter Pecan", "Strawberry", "Chocolate Chip", "Cherry", "Coffee" };
// Constructor for ThreadIceCream class
public ThreadIceCream() {
int randInt = (int) (Math.random() * specialFlavors.length);
flavor = specialFlavors[randInt];
System.out.println("Enjoy your " + flavor + " IceCream!");
} }
The ThreadIceCream class is a simple class that creates an IceCream object with a random flavor every time the class is initialized. Here is the TestStub I am using.
public class TestStub {
public static void main(String[] args) {
ThreadIceCream Th1 = new ThreadIceCream();
ThreadIceCream Th2 = new ThreadIceCream();
} }
Now I want to create 10 Icecreams (i.e. Create 10 instances of the ThreadIceCream class simultaneously) and I want to use threads in Java to do this. I tried a few things but they were no were close.
Well it's not really that hard:
Thread[] threads = new Thread[10];
for(int i = 0; i < 10; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
ThreadIceCream tic = new ThreadIceCream();
}
});
threads[i].start();
}
for(int i = 0; i < 10; i++) {
threads[i].join();
}
Sure, this won't do much because the work performed by each thread is so small that the overhead to start the threads is actually higher, but whatever.
You should also learn to use the ExecutorService for higher efficiency. Pure threads are heavyweight and are rarely a good solution for anything, especially in groups. Here's an ExecutorService version of the above:
ExecutorService exec = Executors.newFixedThreadPool(10);
for(int i = 0; i < 10; i++) {
exec.submit(new Runnable() {
public void run() {
ThreadIceCream tic = new ThreadIceCream();
}
});
}
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
Here we are creating a pool of 10 threads and submitting 10 tasks. The threads are recycled betweeen task executions, so only 10 threads are ever created, no matter how many tasks you submit. Since the tasks are so small several tasks may even be executed on the same thread, but that's actually a good thing.

Categories

Resources