How to correctly use the Threads - java

I have the following task :
Create Class called: ElementsProvider(int n, List elements) that will provide N random elements into given list.
Elements Provider will be an thread.
Try create 4 instances, each of this instance will add 1000 random elements into the list.
start all instances at once and wait until they end.
print list size.
And here is what is did ,
Main:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ElementsProvider implements Runnable{
private final List<Integer> list;
private final int n;
public ElementsProvider(List<Integer> list, int n){
this.list = list;
this.n = n;
}
#Override
public void run() {
Random random = new Random();
for (int i = 0; i < n; i++) {
list.add(random.nextInt());
}
}
public static void main(String[] args) throws InterruptedException {
List<Integer> list = new ArrayList<>();
int n = 1000;
ElementsProvider e1 = new ElementsProvider(list, n);
ElementsProvider e2 = new ElementsProvider(list, n);
ElementsProvider e3 = new ElementsProvider(list, n);
ElementsProvider e4 = new ElementsProvider(list, n);
Thread t1 = new Thread(e1);
Thread t2 = new Thread(e2);
Thread t3 = new Thread(e3);
Thread t4 = new Thread(e4);
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println(list);
}
}
Apparently I got that the task is not ok.
Feedback that I got is :
wrong, try to print list size, it will be different each time You run the program.
Can someone point me where I am mistaking please?

You proposed this change in a comment on your original question, above:
#Override
public void run() {
synchronized (ElementsProvider.class) {
Random random = new Random();
for (int i = 0; i < n; i++) {
list.add(random.nextInt());
}
}
}
O.K., That will ensure that your program always prints the correct answer, but it does so by making your program effectively single-threaded. When you put the entire body of the threads' run() method in a single synchronized block, you prevent them from running concurrently. But, running concurrently is the only reason to use threads.
You need to synchronize a smaller part of the code. The only variable that the threads share is the list. There is no reason for new Random() to be inside the synchronized block, and there is no reason for random.nextInt() to be inside it. The only thing that needs to be inside the synchronized block is the list.add() call.

I'd add a static semaphore to the your ElementsProvider class:
public class ElementsProvider implements Runnable {
private final List<Integer> list;
private final int n;
private static Semaphore semaphore = new Semaphore(1);
public ElementsProvider(List<Integer> list, int n) {
this.list = list;
this.n = n;
}
#Override
public void run() {
Random random = new Random();
List<Integer> l = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
l.add(random.nextInt());
}
try {
semaphore.acquire();
System.out.println("Adding " + l.size() + " elements to list");
list.addAll(l);
} catch (Exception e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
}

Related

Sum of all the elements in an array with ExecutorService pool not working

I am trying to understand ExecutorService and i want to do the sum of all the elements of an array. I did two methods, one that makes the sum serially (just a for loop that sums all the elements) and other concurrently with a pool. My problem is that the total sum from using ExecutorService is off with the serial sum almost all the time, sometimes even just by one.
package sumArregloConc;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class SumaArregloMain {
private final static int cantElem = 1000;
private static ExecutorService tpool = Executors.newCachedThreadPool();
public static void main(String[] args)
{
int[] arreglo = generarArreglo(cantElem); //generate the array with random numbers
System.out.println(sumaSerial(arreglo));
System.out.println(sumaConcurrente(arreglo));
}
public static int sumaSerial(int[] arreglo)
{
int suma = 0;
for(int i =0; i< arreglo.length; i++)
{
suma += arreglo[i];
}
return suma;
}
public static int sumaConcurrente(int[] arreglo)
{
AtomicInteger total = new AtomicInteger(0);
for(int i = 1 ; i < cantElem; i++){
int a = arreglo[i];
Thread thread = new Thread(new Runnable(){
public void run() {
int res = a;
total.addAndGet(res);
return;
}});
tpool.submit(thread);
}
tpool.shutdown(); //wait for everything to finish
return total.get();
}
public static int[] generarArreglo(int cantElem)
{
int[] arreglo = new int[cantElem];
Random rand = new Random();
for(int i = 0; i < cantElem; i++)
{
arreglo[i] = rand.nextInt(10);
}
return arreglo;
}
}
Can someone tell what is wrong?
Found the error. First what Eric said about awaitTermination and Runnable, but the main bug was just that the loop started at i = 1 instead of i = 0, silly mistake.
public static int sumaConcurrente(int[] arreglo)
{
AtomicInteger total = new AtomicInteger(0);
for(int i = 0 ; i < cantElem; i++){
int a = arreglo[i];
tpool.submit(new Runnable(){
public void run() {
total.addAndGet(a);
return;
}
});
}
tpool.shutdown(); //wait for everything to finish
try {
tpool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
}
return total.get();
}

Changing an arrays elements with thread

I need the change the elements of an array by using a thread. It should change (add or sub an integer number) an element randomly, sleep for 2 sec and change another one randomly.
So i created my array and my thread, but I don't know how to change it.
public static void main(String[] args) {
int [] myarray= new int[5];
Thread x= new Thread();
x.start();
try
{
x.sleep(2000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
public class myThread implements Runnable {
public myThread(){ //an empty constructor, to pass parameters
}
public void run(){
}
public void update(){ //i tohught i could use that for changing elements
}
First, you have to create an class declaration, that accepts required arr and implements run() method with logic.
public static class MyThread implements Runnable {
private final int[] arr;
private final Random random = new Random();
private MyThread(int[] arr) {
this.arr = arr;
}
#Override
public void run() {
try {
while (true) {
// wait for 2 seconds
Thread.sleep(TimeUnit.SECONDS.toMillis(2));
// randomly choose array element
int i = random.nextInt(arr.length);
// randomly choose increment or decrement an elements
boolean add = random.nextBoolean();
// lock WHOLE array for modification
synchronized (arr) {
arr[i] = add ? arr[i] + 1 : arr[i] - 1;
}
}
} catch(InterruptedException e) {
}
}
}
Second, you have to create an array and required number of threads for modifications.
// create an array
int[] arr = new int[5];
// create threads and start
for (int i = 0; i < 20; i++)
new Thread(new MyThread(arr)).start();
That's all basically. Sure, it is possible to not lock whole array to modify only one elements, but this is another story.

LinkedBlockingQueue only return one of mupltiple threads

I've made a class that counts words in given files within the same directory. Seeing as the files are very large, I've decided to achieve the count of multiple files using multiple threads.
When running the DriverClass as specified below, it get's stuck at thread one.
What am I doing wrong? As I'm iterating over queue.take(), one would expect the parser to wait for something to retrieve and move on. Getting stuck at thread 1 makes me suspect an error when putting() into the queue.
Thank's, in advance!
DriverClass:
public class WordCountTest {
public static void main(String[] args){
if (args.length<1){
System.out.println("Please specify, atleast, one file");
}
BlockingQueue<Integer> threadQueue = new LinkedBlockingQueue<>();
Runnable r;
Thread t;
for (int i = 0; i<args.length; i++){
r = new WordCount(args[i], threadQueue);
t = new Thread(r);
t.start();
int total = 0;
for (int k = 0; k<args.length; k++){
try {
total += threadQueue.take();
} catch (InterruptedException e){
}
}
System.out.println("Total wordcount: " + total);
}
}
}
WordCountClass:
public class WordCount implements Runnable {
private int myId = 0;
private String _file;
private BlockingQueue<Integer> _queue;
private static int id = 0;
public WordCount(String file, BlockingQueue<Integer> queue){
_queue = queue;
_file = file;
myId = ++id;
}
#Override
public void run() {
System.out.println("Thread " + myId + " running");
try {
_queue.put(countWord(_file));
} catch (InterruptedException e){
}
}
public int countWord(String file){
int count = 0;
try {
Scanner in = new Scanner(new FileReader(file));
while (in.hasNext()){
count++;
in.next();
}
} catch (IOException e){
System.out.println("File," + file + ",not found");
}
return count;
}
}
The problem is that you're using a nested loop, when you should be using two separate loops: one to start the WordCounts, another to collect the results, something like
public class WordCountTest {
public static void main(String[] args){
Queue<Integer> threadQueue = new ConcurrentLinkedQueue<>();
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
CountDownLatch latch = new CountDownLatch(args.length);
for (int i = 0; i<args.length; i++){
CompletableFuture.runAsync(new WordCount(args[i], threadQueue), executor)
.thenRunAsync(latch.countDown(), executor);
}
latch.await();
int sum = 0;
for(Integer i : threadQueue) {
sum += i;
}
}
}
Or however you want to implement it, the point being that you shouldn't start collecting results until all of the WordCounts have started.
You are waiting for all the results after the first thread is started. Perhaps you intended to wait for the results after all the threads have started.
Note: if you create more threads than you have CPUs its likely to be slower. I suggest using a fixed thread pool instead.

Parallelizing generation of permutations in JAVA

I am trying to generate all permutations of some String in parallel using algorithm from here
(difference is that my code also handles Strings containing repetitive characters). I am using SynchrounousQueue for thread synchronization. Generator generates a permutation and Printer takes it and prints it. My code:
import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
public class PermBlockingQueue {
public static int printers = 4;
public static String str = "ABCD";
public static class Generator implements Runnable {
private final BlockingQueue q;
private final String pref;
public Generator(BlockingQueue q, String pref) {
this.q = q;
this.pref = pref;
}
public void permutations(String pref, String str) {
int n = str.length();
if (n == 0) {
try {
q.put(pref);
} catch (InterruptedException ex) { }
} else {
for (int i = 0; i < str.length(); i++) {
if (str.indexOf(str.charAt(i), i + 1) != -1) {
continue;
}
permutations(pref + str.charAt(i), str.substring(0, i) + str.substring(i + 1));
}
}
}
#Override
public void run() {
int k = str.indexOf(pref);
permutations(pref, str.substring(0, k) + str.substring(k + 1)));
//Sending messages for printers to quit
try {
for (int x = 0; x < printers; x++) {
q.put("");
}
} catch (InterruptedException ex) {
}
}
}
public static class Printer implements Runnable {
private final BlockingQueue q;
public Printer(BlockingQueue q) {
this.q = q;
}
#Override
public void run() {
try {
String permut;
while (!((permut = (String) q.take()).equals(""))) {
System.out.println(permut);
}
} catch (InterruptedException ex) {
}
}
}
public static void main(String[] args) throws InterruptedException {
ArrayList<Thread> threads = new ArrayList<>();
BlockingQueue q = new SynchronousQueue();
Thread th1 = new Thread(new Generator(q, "A"));
Thread th2 = new Thread(new Generator(q, "B"));
Thread th3 = new Thread(new Generator(q, "C"));
Thread th4 = new Thread(new Generator(q, "D"));
threads.add(th1);
threads.add(th2);
threads.add(th3);
threads.add(th4);
for (int i = 0; i < printers; i++) {
threads.add(new Thread(new Printer(q)));
}
for (Thread th : threads.toArray(new Thread[threads.size()])) {
th.start();
}
for (Thread th : threads.toArray(new Thread[threads.size()])) {
th.join();
}
}
}
In sequential program method permutations(String pref, String str) works as expected. As far as synchronization goes, there are no problems as long as I am not using recursive method. In this program however, I am using recursive method and it deadlocks. I am guessing that Generator locks itself because multiple values are returned to it and further more, nothing gets printed. Also, if I put print statement in permutations method before return statement,
if (n == 0) {
System.out.println(pref);
return pref;
}
I get the expected output, which in case of "ABCD" is (4! = 24 permutations):
ABCD
ABDC
ACBD
....
DBAC
DBCA
DCAB
DCBA
Of course these values are not printed by Printers who are waiting for input from Generators and program is deadlocked.
So what exactly happens with recursive method here? And most importantly, how do I approach this kind of problem?
Thank you.
Edit: I've changed my code a little bit, considering the fact, that
q.put(permutations(pref, str.substring(0, k) + str.substring(k + 1)));
didn't really made much of a sense (correct me, if I'm wrong). This is because, in my mind, it creates a ambiguity as to which permutation should be put in SynchronousQueue, as single call to permutation yields more than one permutation (at least in my example).
Now I'm putting permutations into queue inside permutations method, whereas in Generators' run() I only call permutations. This gives better results: instead of no permutations getting printed, some are printed. This 'some' varies with each execution and program still gets deadlocked.

make a thread which recieves values from other threads

This program in Java creates a list of 15 numbers and creates 3 threads to search for the maximum in a given interval. I want to create another thread that takes those 3 numbers and get the maximum. but i don't know how to get those values in the other thread.
public class apple implements Runnable{
String name;
int time, number, first, last, maximum;
int[] array = {12, 32, 54 ,64, 656, 756, 765 ,43, 34, 54,5 ,45 ,6 , 5, 65};
public apple(String s, int f, int l){
name = s;
first = f;
last = l;
maximum = array[0];
}
public void run(){
try{
for(int i = first; i < last; i++ )
{
if(maximum < array[i])
{
maximum = array[i];
}
}
System.out.println("Thread"+ name + "maximum = " + maximum);
}catch(Exception e){}
}
public static void main(String[] args){
Thread t1 = new Thread(new apple("1 ", 0, 5));
Thread t2 = new Thread(new apple("2 ", 5, 10 ));
Thread t3 = new Thread(new apple("3 ", 10, 15));
try{
t1.start();
t2.start();
t3.start();
}catch(Exception e){}
}
}
Here is how ExecutorService and ExecutorCompletionService can solve it:
public class MaxFinder {
private int[] values;
private int threadsCount;
public MaxFinder(int[] values, int threadsCount) {
this.values = values;
this.threadsCount = threadsCount;
}
public int find() throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(threadsCount);
ExecutorCompletionService<Integer> cs = new ExecutorCompletionService<Integer>(executor);
// Split the work
int perThread = values.length / threadsCount;
int from = 0;
for(int i = 0; i < threadsCount - 1; i++) {
cs.submit(new Worker(from, from + perThread));
from += perThread;
}
cs.submit(new Worker(from,values.length));
// Start collecting results as they arrive
int globalMax = values[0];
try {
for(int i = 0; i < threadsCount; i++){
int v = cs.take().get();
if (v > globalMax)
globalMax = v;
}
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
executor.shutdown();
return globalMax;
}
private class Worker implements Callable<Integer> {
private int fromIndex;
private int toIndex;
public Worker(int fromIndex, int toIndex) {
this.fromIndex = fromIndex;
this.toIndex = toIndex;
}
#Override
public Integer call() {
int max = values[0];
for(int i = fromIndex; i<toIndex; i++){
if (values[i] > max)
max = values[i];
}
return max;
}
}
}
In this solution, N threads work concurrently, each on its portion of the array. The caller thread is responsible for gathering the local maximums as they arrive, and find the global maximum. This solution uses some non-trivial concurrency tools from java.util.concurrent package.
If you prefer a solution that only uses primitive synchronization tools, then you should use a synchronized block in the worker threads, that sets the maximum in some data member and then notifies the collector thread. The collector thread should be in a loop, waiting for notification and then examining the new number, and updating the global maximum if needed. This "consumer producer" model requires careful synchronization.
Based on the code you have, the simplest solution is to join the main thread to each instance thread and then get the max value from them for comparison purposes. Like so:
int globalMax;
try{
t1.start();
t2.start();
t3.start();
t1.join();
globalMax = t1.maximum;
t2.join();
if (t2.maximum > globalMax) {
globalMax = t2.maximum;
}
t3.join();
if (t3.maximum > globalMax) {
globalMax = t3.maximum;
}
} catch(Exception e){
}
Instead of implementing Runnable, try implementing Callable, which is capable of returning a result. The tutorial given here is a good source for describing how to do this.
Another approach to your problem could be to create an object which each apple instance (not sure why you've called it this) could register its maximum with the object. This new class could be passed into each apple constructor, then the apple could call a method, passing its own maximum into this.
For instance:
public class MaximumOfMaximumsFinder implements Runnable {
private List<Integer> maximums = new ArrayList<Integer>();
public void registerSingleMaximum(Integer max) {
maximums.add(max);
}
public void run() {
// use similar logic to find the maximum
}
}
There are several issues around making sure this is coordinated with the other threads, I'll leave this to you, since there's some interesting things to think about.

Categories

Resources