Converting Runnable into an array of runnable Workers - java

I am trying to create a runnable array that stores worker classes then use a Thread array to start the works.
public class SimpleThreads {
public static void main(String[] args) {
System.out.println("main starts.");
int num1 = 5;
int num2 = 7;
// create Workers
Runnable r1 = new Worker(num1, num2);
Runnable r2 = new Worker(num1 * 10, num2 * 10);
Runnable[] runs = new Worker(num1, num2);
// create Threads to run Workers
Thread[] threads = new Thread[args.length];
for (int i = 0; i < args.length; i++) {
threads[i] = new Thread(runs[i]);
}
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
// start threads
t1.start();
t2.start();
// Returns the adition to the main
System.out.println(((Worker) r1).doCalc());
System.out.println(((Worker) r2).doCalc());
int grandTotal = 0;
grandTotal = ((Worker) r1).doCalc() + ((Worker) r2).doCalc();
System.out.println("The Grand Total " + grandTotal);
System.out.println("main ends.");
}
}
/*
* the class that becomes a thread, can be named anything, must have
* "implements Runnable" which requires the public void run() method
*/
class Worker implements Runnable {
private int val1;
private int val2;
private long threadId;
// constructor
Worker(int val1, int val2) {
this.val1 = val1;
this.val2 = val2;
}
// required method
public void run() {
threadId = Thread.currentThread().getId();
doCalc();
}
// does the actual work
public int doCalc() {
return val1 + val2;
// System.out.printf("[%03d] %3d + %3d = %3d\n", threadId, val1, val2, result);
}
}
Basically, can someone help me figure out what I am doing wrong here? I get this error Type mismatch: cannot convert from Worker to Runnable[]Java(16777233)
My Expected results should be
Creating an array of runnable workers
Then using that array of runnable workers with my thread array and starting threads automatically, instead of hardcoding each thread 1 by 1.

It seems you are a little mixed up in concepts.
You store all your threads and runnables in arrays, but then you go ahead and create non-array instances and use those.
You declare runnables and threads, but then you go ahead and call the calculation method straight from your main thread.
Let's clean up the startup part first:
public class SimpleThreads {
public static void main(String[] args) {
System.out.println("main starts.");
int num1 = 5;
int num2 = 7;
// Build an array of workers.
Worker[] workers = new Worker[] {
new Worker(num1, num2),
new Worker(num1 * 10, num2 * 10)
};
// create Threads to run Workers and start them
Thread[] threads = new Thread[workers.length];
for (int i = 0; i < workers.length; i++)
{
threads[i] = new Thread(workers[i]);
threads[i].start();
}
So, now we have an array of Workers and an array of Threads.
You could declare the workers array to be of type Runnable if you wish, but we want to use the worker's methods later.
Lets see if we can get data out of the workers. We'll add a getResult() method.
class Worker implements Runnable {
private int val1;
private int val2;
private int result;
// constructor
Worker(int val1, int val2) {
this.val1 = val1;
this.val2 = val2;
}
// required method
public void run() {
doCalc();
}
// does the actual work
private void doCalc() {
result = val1 + val2;
}
public int getResult() { return result; }
}
So, once our worker has completed, we can call getResult() to see what it's final answer is.
So, back to the main, let's wait for the threads to finish, and then add up their results.
int grandTotal = 0;
// Wait for threads to finish
for(int i=0;i<threads.length;i++)
{
threads[i].join();
}
// Read their results
for (int i=0; i<workers.length;i++)
{
grandTotal += workers[i].getResult();
}
System.out.println("The Grand Total " + grandTotal);

Related

How can I assign a value to the threadArray variable in Task1 , Task2, Task3 class run() method?

I have to insert the elements using three threads by creating three classes, namely Task1,Task2 and Task3. The values to be inserted into the array are 0,1,2,....299.
Override the run method in the threads. Three integer i,j, and k representing the number of elements each thread should append inside the given array.
Thread one should append 0 to i-1 inside the array,thread two should append i to i+j-1 inside the array,and the third thread should append i+j to 299 inide the array.
Threads one and two must run simultaneously, and the values of the threads one and two must be inserted inside the indices of the array from 0 to i+j-1 randomly.The third thread should start only after the first two threads have been executed completely.
In these code three task are given.
first task and second task start executing the thread at the same time and after completion of first two task then only third task start. If these situation getting correct then test() method return true.
public static final int[] threadArray = new int[300]; how I add random number into these array using Task1 Task2 and Task3 class.
Input :
80
130
90
Output :
True
import java.util.Scanner;
class Task1 extends Thread
{
static int a = 0;
static int beg = 0;
public void run()
{
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Task2 extends Thread
{
static int a = 0;
static int beg = 0;
#Override
public void run()
{
// TODO Auto-generated method stub
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
}
}
}
class Task3 extends Thread
{
static int a = 0;
static int beg = 0;
public void run()
{
// TODO Auto-generated method stub
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
}
}
}
public class Solution
{
public static final int[] threadArray = new int[300];
public static volatile String i = 0+"";
public boolean test() throws InterruptedException
{
Task1 task1 = new Task1();
Task2 task2 = new Task2();
Task3 task3 = new Task3();
Thread task2Thread = new Thread(task2);
Thread task3Thread = new Thread(task3);
task1.start();
task2Thread.start();
task1.join();
task2Thread.join();
task3Thread.start();
int first = Task1.a+Task2.a;
int containsSecondThread = Task1.a;
String oneAndTwo = "";
String sizeOfTask1 = "";
for(int i=0;i<first;i++)
{
oneAndTwo += threadArray[i]+" ";
}
for(int i=0;i<containsSecondThread;i++)
{
sizeOfTask1 += threadArray[i]+" ";
}
int begOfTask3 = Task3.beg;
String checkingString = "";
for(int i=begOfTask3;i<threadArray.length;i++)
{
checkingString += i + " ";
}
String task3String = "";
for(int j = begOfTask3;j<threadArray.length;j++)
{
task3String += threadArray[j]+" ";
}
if((!oneAndTwo.contains(begOfTask3+"") && sizeOfTask1.contains(Task2.beg+"")) || task3String.equals(checkingString))
{
return true;
}
return false;
}
public static void main(String[] args) throws InterruptedException
{
Scanner sc= new Scanner(System.in);
Solution solution = new Solution();
int one = sc.nextInt();
Task1.a = one;
Task1.beg = 0;
int two = sc.nextInt();
Task2.a = two;
Task2.beg = one;
int three = sc.nextInt();
Task3.a = three;
Task3.beg = one+two;
System.out.print(solution.test());
}
}
First, some observations regarding your code: Instead of using static variables in the classes (i.e., Task1, Task2, and Task3) that extend the class Thread (to understand why have a look at Why are static variables considered evil?):
static int a = 0;
static int beg = 0;
use non-static final fields, and initialize them via the constructor:
class Task1 extends Thread
{
private final int begin;
private final int end;
Task1(int begin, int end){
this.begin = begin;
this.end = end;
}
public void run(){
for(int i=begin; i<= end; i++)
....
}
}
adapt the main method accordingly:
public static void main(String[] args){
...
Task1 task1 = new Task1(begin, end);
}
and then pass the tasks-related objects as parameters of to the test method:
public boolean test(Task1 task1, Task2 task2, Task3 task3){
...
}
For the concatenation of the strings use StringBuilder:
StringBuilder oneAndTwo = new StringBuilder();
for(int i=0;i<first;i++)
{
oneAndTwo.append(threadArray[i]).append(" ");
}
This looks wrong:
Task1.a = one;
Task1.beg = 0;
by looking at the loop of the run method from Task1, this means that, if Task1.a is not a negative number, then Task1 will not do any work.
To use the threads to generate the random values of the array:
int[] threadArray = new int[300];
you can start by extracting a method to generate those random values, based on formula:
r.nextInt(high-low) + low;
this formula generates a random value between low and high.
Adapt the tasks, accordingly:
class Task1 extends Thread
{
private final Random random_values = new Random();
private final int low;
private final int high;
...
public int generate_random(){
return r.nextInt(high-low) + low;
}
public void run()
{
for(....)
{
Solution.threadArray[i] = generate_random();
...
}
}
}
Make sure to pass to the threads the information about the range of the random values to be generated (i.e., the low and high parameters), and the reference to the array that will be filled up with those random values (i.e., array int[] threadArray) . Also make sure that you split the iterations int[] threadArray among the threads. Therefore, each thread should generate a chunk of the random values. An example of such distribution would be:
Thread 1 : 0 to 100;
Thread 2 : 100 to 200;
Thread 3 : 200 to 300;
You can make this more robust and divide the array length by the number to threads and assign the work among threads, accordingly.
I could have provided you with the entire solution, but I feel that is better instead if I give you the pointers so that you can do it in your own.
EDIT: Based on the new edit of your question:
You just need to adapt the Task classes as follows:
class Task1 extends Thread {
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg;i < a;i++)
Solution.threadArray[i] = i;
}
}
class Task2 extends Thread {
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg; i< beg + a;i++)
Solution.threadArray[i] = i;
}
}
class Task3 extends Thread{
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg;i< a + beg;i++)
Solution.threadArray[i] = i;
}
}
Thread1 and Thread2 are supposed to access Common Resource in threadArray[0... Task1.a+Task2+a]. So we have to make use of static volatile variable i declared in Solution Class.
class Task1 extends Thread
{
static int a=0,beg=0;
public void run()
{
int k=Task1.beg;
int i1=0;
while(i1<Task1.a)
{
Solution.threadArray[Integer.parseInt(Solution.i)]=k++;
int a1=Integer.parseInt(Solution.i);
a1++;i1++;
Solution.i=a1+"";
try{
Thread.sleep(1);
}
catch(InterruptedException e){}
}
}
}
class Task2 extends Thread
{
static int a=0,beg=0;
public void run()
{
int y=0;
int k=Task2.beg;
while(y<Task2.a)
{
Solution.threadArray[Integer.parseInt(Solution.i)]=k++;
int a1=Integer.parseInt(Solution.i);
a1++;y++;
Solution.i=a1+"";
try{
Thread.sleep(1);
}
catch(InterruptedException e){}
}
}
}
Thread3 work independently after First 2 threads complete.
class Task3 extends Thread
{
static int beg=0,a=0;
public void run()
{
for(int i=Task3.beg;i<Task3.beg+Task3.a;i++)
{
Solution.threadArray[i]=i;
}
}
}

calculating sum of numbers from 1 to 100,000,000 using multithreading in java

I tried to write a program that prints sum of numbers from 1 to 100,000,000 using multithreading in Java. The idea is that the 1st thread will calculate the sum of the numbers from 1 to 25,000,000; the 2nd thread will calculate the sum of the numbers
from 25,000,001 to 50,000,000, and so forth. The main thread will have to print out the sum after
gathering the results. I tried extending the Thread class.
class Thread1 extends Thread{
public void run() {
//int i=num;
int i;
for(i=1;i<25000001;i++)
i+=i;
System.out.println("Thread 1: the sum is: "+i);
mainThread m=new mainThread();
m.guther(i);
}
}
class Thread2 extends Thread{
public void run() {
//int i=num;
int i;
for(i=25000001;i<50000001;i++)
i+=i;
System.out.println("Thread 2: the sum is: "+i);
mainThread m=new mainThread();
m.guther(i);
}
}
class Thread3 extends Thread{
public void run() {
//int i=num;
int i;
for(i=50000001;i<75000001;i++)
i+=i;
System.out.println("Thread 3: the sum is: "+i);
mainThread m=new mainThread();
m.guther(i);
}
}
class Thread4 extends Thread{
public void run() {
//int i=num;
int i;
for(i=75000001;i<100000001;i++)
i+=i;
System.out.println("Thread 4: the sum is: "+i);
mainThread m=new mainThread();
m.guther(i);
}
}
class mainThread{
void guther(int total) {
for(int i=1;i<=1;i++)
total+=total;
System.out.println("mainThread : the sum is: "+total);
}
/*public void run() {
mainThread m=new mainThread();
System.out.println(Thread.currentThread().getId()+"the total is: ");
}*/
}
public class startThread {
public static void main(String[] args) {
//thread 1
Thread1 t1=new Thread1();
t1.start();
//t1.run(1);
//thread 2
Thread2 t2=new Thread2();
t2.start();
//t2.run(25000001);
//thread 3
Thread3 t3=new Thread3();
t3.start();
//t3.run(50000001);
//thread 4
Thread4 t4=new Thread4();
t4.start();
//t4.run(75000001);
//int total=t1.run(1)+t2.run(25000001)+t3.run(50000001)+t4.run(75000001);
//System.out.println("the total is: "+total);
//mainThread m=new mainThread();
}
}
You're creating new instances of mainThread inside every single Thread implementation. This will be a problem, because they will not share the same result. You're also not keeping that result anywhere.
Multithreading is complex, and comes with a lot of issues, so I suggest you read on locks & synchronization of threads: https://www.tutorialspoint.com/java/java_multithreading.htm https://www.tutorialspoint.com/java/java_thread_synchronization.htm
[Edit]
I got this wrong in the original answer. There are much simpler ways of calculating the sum of all of these: https://math.stackexchange.com/questions/593318/factorial-but-with-addition
You can use ForkJoinPool framework. Define the RecursiveTask that returns a value and sum the processed sub-results.
class SumRecursiveAction extends RecursiveTask<BigInteger> {
private static final int PIVOT = 1000;
private final int start;
private final int end;
private final List<Integer> list;
public SumRecursiveAction(List<Integer> list, int start, int end) {
this.start = start;
this.end = end;
this.list = list;
}
protected BigInteger compute() {
if (end - start <= PIVOT) {
// process if the range is within the pivot
BigInteger sum = BigInteger.ZERO;
for (int i = start; i < end; i++) {
sum = sum.add(BigInteger.valueOf(list.get(i)));
}
return sum;
} else {
// or else delegate the task, fork and join
int middle = start + ((end-start) / 2);
RecursiveTask<BigInteger> otherTask = new SumRecursiveAction(list, start, middle);
otherTask.fork();
return new SumRecursiveAction(list, middle, end)
.compute()
.add(otherTask.join());
}
}
}
Usage:
List<Integer> list = IntStream.range(0, 100_000).boxed().collect(Collectors.toList());
ForkJoinTask<BigInteger> task = new SumRecursiveAction(list,0, list.size());
ForkJoinPool pool = new ForkJoinPool();
BigInteger sum = pool.invoke(task);
System.out.println("Sum: " + sum);

java multi threads access Hashtable

I tried to use multi threads to access the Hashtable, since Hashtable is thread safe on get. But I cannot get it work.
I thought the sum of local counter should be equal to the size of the Hashtable or the global_counter. But it is not.
Serveral threads get java.util.NoSuchElementException: Hashtable Enumerator error. I think the error is due to the enumeration of Hashtable. Is that so?
TestMain:
public class TestMain {
// MAIN
public static void main(String argv[]) throws InterruptedException
{
Hashtable<Integer, Integer> id2 = new Hashtable<Integer, Integer>();
for (int i = 0; i < 100000; ++i)
id2.put(i, i+1);
int num_threads = Runtime.getRuntime().availableProcessors() - 1;
ExecutorService ExeSvc = Executors.newFixedThreadPool(num_threads);
for (int i = 0; i < num_threads; ++i)
{
ExeSvc.execute(new CalcLink(id2, i));
}
ExeSvc.shutdown();
ExeSvc.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
CalcLink:
public class CalcLink implements Runnable {
private Hashtable<Integer, Integer> linktable;
private static Enumeration keys;
private static int global_counter;
private int thread_id;
private int total_size;
public CalcLink(Hashtable<Integer, Integer> lt, int id)
{
linktable = lt;
keys = lt.keys();
thread_id = id;
total_size = lt.size();
global_counter = 0;
}
private synchronized void increment()
{
++global_counter;
}
#Override
public void run()
{
int counter = 0;
while (keys.hasMoreElements())
{
++counter;
increment();
Integer key = (Integer)keys.nextElement();
Integer value = linktable.get(key);
}
System.out.println("local counter = " + Integer.toString(counter));
if (thread_id == 1)
System.out.println("global counter = " + Integer.toString(global_counter));
}
}
while (keys.hasMoreElements()) // here you check whether there's an element
{
++counter; // other stuff...
increment(); // other stuff...
Integer key = (Integer)keys.nextElement(); // only here you step
During you are in the other stuff in "this thread" you can enter the other stuff in another thread, thus IMHO you might see higher number in the global counter than what you expect.
This is also the reason you see NoSuchElementException in some of the threads, that entered to the "other stuff" together, but are trying to catch the last element. The later threads won't have the element there when they get to nextElement();
The problem is that this block isn't synchronized :
while (keys.hasMoreElements())
{
++counter;
increment();
Integer key = (Integer)keys.nextElement();
Integer value = linktable.get(key);
}
keys.hasMoreElements() can be evaluated to true in multiple threads when there is still only one element in the Enumeration. In those threads : the first one reaching keys.nextElement() will be fine, but all the others will raise a NoSuchElementException
Try this :
#Override
public void run()
{
int counter = 0;
synchronized (keys){
while (keys.hasMoreElements())
{
++counter;
increment();
Integer key = (Integer)keys.nextElement();
Integer value = linktable.get(key);
}
}
System.out.println("local counter = " + Integer.toString(counter));
if (thread_id == 1)
System.out.println("global counter = " + Integer.toString(global_counter));
}
An naive solution: I just let each thread to process Length / num_threads of records. Only the last thread will process length/num_threads + length%num_threads records.

Return Value from Java Thread Class

So below is a simple Java class using multithreading, and my question is, is there a way for me to store the randomNumber from each thread (maybe in a variable called randomNumberOne or randomNumberTwo), so that I can use those to possibly get the sum of both and return it?
I know this example sounds stupid but basically with my real code I am returning a value from each of my threads and want to get the average of them. I haven't found any solution for returning values in threads in java (also I am new to multithreading completely).
public class Example {
public static void main(String[] args){
MathThread one = new MathThread();
MathThread two = new MathThread();
one.start();
two.start();
}
}
class MathThread extends Thread{
public MathThread(){
}
public void run(){
Random rand = new Random();
int randomNumber = rand.nextInt((100 - 1) + 1) + 1;
System.out.println(randomNumber);
}
Output
5
33
Add a result variable to your MathThread class and get the value after you join the thread:
class MathThread extends Thread
{
private int result;
public int getResult()
{
this.join();
return result;
}
public void run()
{
// ...
result = randomNumber;
}
}
one.start();
two.start();
double average = (one.getResult() + two.getResult()) / 2.0;
In Java 8 you can do
IntStream.of(0, 2).parallel()
.map(i -> new Random().nextInt(100)+1)
.forEach(System.out::println);
Without using the Stream API you can do
List<Future> futures = new ArrayList<>();
for (int i = 0; i < 2; i++)
futures.add(ForkJoinPool.commonPool()
.submit(new Callable<Integer>() {
public Integer call() {
return new Random().nextInt(100)+1;
}));
for(Future<Integer> future : futures)
System.out.printl(future.get());
Here is the simple snippet to customize:
// 1. Create and fill callables to execute
List<Callable<Integer>> callables = new LinkedList<>();
// callabels.addAll(makeMeCallables());
// 2. Run using Executor of your choice
ExecutorService service = Executors.newCachedThreadPool();
List<Future<Integer>> results = service.invokeAll(callables);
// 3. Get the results
if (results.get(i).isDone()) {
Future f = result.get(i);
// process f.get()
}

how to spwan recursive calls and for loop iterations in multiple threads in java (if possible)?

I was wondering if it is possible to spawn each loop iteration (each iteration into a thread by itself) and finally collect the result. consider this example, nothing fancy in it at all. Just a simple for-loop, but the idea is to extend on it. The body of for loop does not matter, I just filled up with some code. but basically assume it has some expensive calculation which will take few minutes to complete for each iteration. so I want to do each loop calculation in a separate thread.
public class Threadspawns {
private double[] arr = new double[4];
public void calculations(){
for (int i =2; i < 6; i++){
//expensive calculation
arr[i-2]=Math.pow(i,500);
}
}
public static void main(String[] args){
Threadspawns t = new Threadspawns();
long start = System.currentTimeMillis();
t.calculations();
long end = System.currentTimeMillis();
System.out.println(Arrays.toString(t.arr));
System.out.println("time taken "+ (end-start));
}
}
on the same note,
if it is possible to actually split the recursive calls into multiple threads and collect them as they return.
Example is that of fibonacci
public static int fibonacci(int n){
if (n==0)
return 0;
if (n==1)
return 1;
return fibonacci(n-2)+fibonacci(n-1);
}
It is possible that it cannot be done for fibonacci recurive method. but any other example of paralleling recursive calls between threads IF POSSIBLE would be nice to know.
P.S: I have basic knowledge of Thread and Runnable, but wondering if the above is doable
Solution to your first requirement that is moving the expensive calculation into a Callable task. Hope it find it useful:
import java.util.Arrays;
import java.util.concurrent.*;
public class Threadspawns {
private final int THREAD_COUNT = 8;
private final int CALCULATION_COUNT = 60000;
private double[] arr = new double[CALCULATION_COUNT];
public void calculations() {
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);
ExecutorCompletionService<Double> completionService = new ExecutorCompletionService<Double>(executorService);
for (int i = 2; i < CALCULATION_COUNT; i++) {
completionService.submit(new Calculation(i));
}
//Get from all Future tasks till all tasks completed
for (int i = 2; i < CALCULATION_COUNT; i++) {
try {
arr[i] = completionService.take().get();
} catch (InterruptedException e) {
e.printStackTrace(); //do something
} catch (ExecutionException e) {
e.printStackTrace(); //do something
}
}
}
private static class Calculation implements Callable<Double> {
private final int num;
private Calculation(int num) {
this.num = num;
}
#Override
public Double call() throws Exception {
return Math.pow(num, 500);
}
}
public static void main(String[] args) {
Threadspawns t = new Threadspawns();
long start = System.currentTimeMillis();
t.calculations();
long end = System.currentTimeMillis();
System.out.println(Arrays.toString(t.arr));
System.out.println("time taken " + (end - start));
}
}

Categories