I need to write a simple program that prints prime numbers up to the given number but no longer than 5 seconds.
Is there some kind of timer to use to interrupt a method after a period of time? (but no interruption if printing is shorter than 5 sec).
Thanks in advance.
My code:
public class Primes {
private static boolean checkIfPrime(int x) {
if (x == 2) return true;
if (x % 2 == 0) return false;
int sqrt = (int) Math.sqrt(x) + 1;
for (int i = 3; i < sqrt; i = i + 2) if (x % i == 0) return false;
return true;
}
private static void printPrimesAndOperationTime(int n) {
long start = System.nanoTime();
for (int i = 2; i <= n; i++) if (checkIfPrime(i)) System.out.println(i);
long end = System.nanoTime();
long timeResult = end - start;
System.out.println("Printing time = " + timeResult + " [ns] => "
+ Math.round(timeResult * 100.0 / 1000000) / 100.0 + " [ms]");
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
printPrimesAndOperationTime(n);
}
}
Used Java Concurrency APIs to solve the above problem. please find inline comments for code walk through.
import java.util.Scanner;
import java.util.concurrent.*;
public class TimeoutInterval {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor(); // Start Single thread executor
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
Future future = executor.submit(new Primes(n)); // Find prime no.
try {
future.get(5, TimeUnit.SECONDS); // Set the time out of the prime no. search task
executor.shutdown();
} catch (TimeoutException e) {
executor.shutdown();
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Primes implements Runnable {
private final int number;
Primes(int number) {
this.number = number;
}
#Override
public void run() {
System.out.println("Started..");
printPrimesAndOperationTime(number);
System.out.println("Finished!");
}
private static boolean checkIfPrime(int x) {
if (x == 2) return true;
if (x % 2 == 0) return false;
int sqrt = (int) Math.sqrt(x) + 1;
for (int i = 3; i < sqrt; i = i + 2) if (x % i == 0) return false;
return true;
}
private static void printPrimesAndOperationTime(int n) {
long start = System.nanoTime();
for (int i = 2; i <= n && !Thread.interrupted(); i++) if (checkIfPrime(i)) {
System.out.println(i);
}
long end = System.nanoTime();
long timeResult = end - start;
System.out.println("Printing time = " + timeResult + " [ns] => "
+ Math.round(timeResult * 100.0 / 1000000) / 100.0 + " [ms]");
}
}
Using ExecutorService, you can submit a task with a timeout. On Receiving the TimeoutException, you should call cancel(true) method on the task to interrupt the thread.
From the documentation
... If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
Related
I am working on a prime number generator that is multi-threaded. My goal for this multi-threaded process is that each process will check a single number. I do have somewhat working code, but I am having some issues with the "locking" concept in where the schedular is running 2 process's very closely to each other.
Claimed Lock: 0; Claimed Number: 75827; isPrime: false
Claimed Lock: 1; Claimed Number: 75829; isPrime: false
Claimed Lock: 2; Claimed Number: 75831; isPrime: false
Claimed Lock: 4; Claimed Number: 75835; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 3; Claimed Number: 75833; isPrime: true
Claimed Lock: 6; Claimed Number: 75839; isPrime: false.
(you can see that 2 locks - i.e. 5 get called twice - they should be disctinct)
My main goal of this program is to have 1 thread calculate 1 based prime numbers. There will be n number of threads based on what Java JVM reports back to the int cores variable inside of the code.
Here is a quick explanation of my program:
The program starts out getting the number logical cpu cores of the given computer
Creates a 2d Array of [2] [Num of CPU Cores]
Array[0][i] = Gets filled with 2k+1 (odd numbers) of potential prime numbers (doing this since 2 is the only known prime number that is even)
Array[1][i] = Gets filled with "-1" = Meaning that number is ready to be picked up by a process/thread
The program then spins up n number of threads (based on cpu core count)
A new thread that has been created is supposed to look for the next available Array[1][i] == -1 and change it to the value of 2. (2 represents a process lock and/or the number is being checked if prime or not)
-6a. The n number of child processes check if prime, and will change the Array[1][i] to either 1 or 0 (1 meaning it is prime or 0 meaning its not prime)
-6b. Child Process Terminates
Parent process - Main will busy wait until all Array[1][i] is either 1 or 0
Repeat back to step 3
What am I a missing or doing wrong with this logic? I believe I am missing something with the JVM/OS Schedular. But, I feel like I could be incorrect in this assumption as well? What could I do to remedy this issue?
Here is my Code:
Multi-Threaded Class
class MultithreadCalculate extends Thread {
public void run() {
try {
int indexNum = -1;
for (int i = 0; i < MultiThreadPrimeNumGen.cores; i++) {
if (MultiThreadPrimeNumGen.primeArray[1][i] == -1) {
MultiThreadPrimeNumGen.primeArray[1][i] = 2;
indexNum = i;
break;
}
}
boolean isPrime = true;
for (int i = 2; i < MultiThreadPrimeNumGen.primeArray[0][indexNum]; i++) {
if (MultiThreadPrimeNumGen.primeArray[0][indexNum] % i == 0) {
isPrime = false;
MultiThreadPrimeNumGen.primeArray[1][indexNum] = 0;
break;
}
}
if (isPrime) {
MultiThreadPrimeNumGen.primeArray[1][indexNum] = 1;
}
System.out.println("Thread " + Thread.currentThread().getId() + "; Claimed Lock: " + indexNum + "; Claimed Number: " + MultiThreadPrimeNumGen.primeArray[0][indexNum] + "; isPrime: " + isPrime);
}
catch (Exception e) {
System.out.println("Exception is caught");
}
}
}
Here is the main class:
public class MultiThreadPrimeNumGen {
public static int[][] primeArray;
public static int primeBase = 1;
public static int cores;
private static void fillArray() {
for (int i = 0; i < cores; i++) {
primeBase += 2;
primeArray[0][i] = primeBase;
}
for (int i = 0; i < cores; i++) {
primeArray[1][i] = -1;
}
}
public static void main(String[] args) throws FileNotFoundException {
File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
PrintWriter out = new PrintWriter(file);
//Gets number of CPU Cores
cores = Runtime.getRuntime().availableProcessors();
System.out.println("Number of Cores: " + cores);
while (true) {
primeArray = new int[2][cores];
fillArray();
for (int i = 0; i < cores; i++) {
MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
multithreadCalculate.start();
}
while (true) {
boolean flag = false;
for (int i = 0; i < cores; i++) {
if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
flag = true;
} else {
flag = false;
break;
}
}
if (flag) {
break;
}
}
for (int i = 0; i < cores; i++) {
if (primeArray[1][i] == 1) {
out.println("PrimeNum: " + primeArray[0][i]);
out.flush();
}
}
}
}
}
So you want thread at the loop while filling the array:
Runnable run1 = new Runnable(){
public void run()
{
// Code to fill array
}
};
Thread thread1 = new Thread(run1);
thread1.start();
Runnable run2 = new Runnable(){
public void run()
{
// Code to fill array
}
};
Thread thread2 = new Thread2(run2);
thread2.start();
Actually, I solved my own idea without using Locks. The Idea Came from another user who posted on here: Prime Balpreet. So thank you! What I did was create getters and setters inside of the code. Here is the Modified code:
Multithreaded Class:
class MultithreadCalculate extends Thread {
int PrimeNumCalculate = -1;
int indexNum = -1;
public int getPrimeNumCalculate() {
return PrimeNumCalculate;
}
public void setPrimeNumCalculate(int primeNumCalculate) {
PrimeNumCalculate = primeNumCalculate;
}
public int getIndexNum() {
return indexNum;
}
public void setIndexNum(int indexNum) {
this.indexNum = indexNum;
}
public void run() {
try {
boolean isPrime = true;
for (int i = 2; i < getPrimeNumCalculate(); i++) {
if (getPrimeNumCalculate() % i == 0) {
isPrime = false;
MultiThreadPrimeNumGen.primeArray[0][getIndexNum()] = getPrimeNumCalculate();
MultiThreadPrimeNumGen.primeArray[1][getIndexNum()] = 0;
break;
}
}
if (isPrime) {
MultiThreadPrimeNumGen.primeArray[0][getIndexNum()] = getPrimeNumCalculate();
MultiThreadPrimeNumGen.primeArray[1][getIndexNum()] = 1;
}
System.out.println("Thread " + Thread.currentThread().getId() + "; Index: " + getIndexNum() + "; Number: " + getPrimeNumCalculate() + "; isPrime: " + isPrime);
}
catch (Exception e) {
System.out.println("Exception is caught");
}
}
}
Here is my Main Class:
public class MultiThreadPrimeNumGen {
public static int [][] primeArray;
public static int primeBase = 1;
public static int cores;
private static void fillArray() {
for (int i = 0; i < cores; i++) {
primeArray[0][i] = -1;
}
for (int i = 0; i < cores; i++) {
primeArray[1][i] = -1;
}
}
public static void main(String[] args) throws FileNotFoundException {
File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
PrintWriter out = new PrintWriter(file);
cores = Runtime.getRuntime().availableProcessors();
System.out.println("Number of Cores: " + cores);
out.println(2);
out.flush();
while (true) {
primeArray = new int[2][cores];
fillArray();
for (int i = 0; i < cores; i++) {
MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
multithreadCalculate.setPrimeNumCalculate(primeBase += 2);
multithreadCalculate.setIndexNum(i);
multithreadCalculate.start();
}
while (true) {
boolean flag = false;
for (int i = 0; i < cores; i++) {
if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
flag = true;
} else {
flag = false;
break;
}
}
if (flag) {
break;
}
}
printMatrix(primeArray);
for (int i = 0; i < cores; i++) {
if (primeArray[1][i] == 1) {
out.println(primeArray[0][i]);
}
}
out.flush();
}
}
public static void printMatrix(int[][] arr) {
if (null == arr || arr.length == 0) {
return;
}
int idx = -1;
StringBuilder[] sbArr = new StringBuilder[arr.length];
for (int[] row : arr) {
sbArr[++idx] = new StringBuilder("[\t");
for (int elem : row) {
sbArr[idx].append(elem).append("\t");
}
sbArr[idx].append("]");
}
for (StringBuilder stringBuilder : sbArr) {
System.out.println(stringBuilder);
}
}
}
I want to make synchronized threads wait for each other. In the example program, each thread simply counts up to 100. I want the threads to wait every 10 outputs.
Because I am preparing for an exam, I would like to use the CyclicBarrier method.
Here is the code:
public class NumberRunner extends Thread {
private int number;
private CyclicBarrier barrier;
public NumberRunner(int n, CyclicBarrier b) {
number = n;
barrier = b;
}
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("Thread " + number + ": " + i);
}
}
and the Main-Class
public class Barriers {
private final static int NUMBER = 3;
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3);
NumberRunner[] runner = new NumberRunner[NUMBER];
for (int i = 0; i < NUMBER; i++) {
runner[i] = new NumberRunner(i, barrier);
}
for (int i = 0; i < NUMBER; i++) {
runner[i].start();
}
}
How do I insert the barriers?
for (int i = 0; i < 100; i++) {
System.out.println("Thread " + number + ": " + i);
if ((i + 1) % 10 == 0) {
try {
barrier.await();
} catch () {}//whatever exceptions b.await() throws
}
}
I decided to optimize the piece of code below but encounter with problem. I tried to change the ArrayList to thread-safe collection by using this discussion but unfortunately something went wrong. The code is compiling but throw the exception.
Exception in thread "main" java.lang.ClassCastException:
java.util.Collections$SynchronizedRandomAccessList cannot be cast to
java.util.ArrayList at
bfpasswrd_multi.PasswordCracker.doItMulti(PasswordCracker.java:73) at
bfpasswrd_multi.PasswordCracker.runMulti(PasswordCracker.java:60) at
bfpasswrd_multi.Test.main(Test.java:16)
Please, tell me what is wrong ?
package bfpasswrd_multi;
import java.util.Scanner;
public class Test
{
public static void main(String[] args)
{
System.out.print("Type password to be cracked: ");
#SuppressWarnings("resource")
String input = new Scanner(System.in).nextLine();
PasswordCracker cracker = new PasswordCracker();
System.out.println("Multithreaded");
cracker.runMulti(input);
cracker = new PasswordCracker();
System.out.println("Finished...");
}
}
package bfpasswrd_multi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class PasswordCracker
{
String passwordToCrack;
public boolean passwordFound;
int min;
int max;
StringBuffer crackedPassword;
public void prepare(String text)
{
passwordToCrack = text;
passwordFound = false;
min = 48;
max = 57; // http://ascii.cl/
crackedPassword = new StringBuffer();
crackedPassword.append((char) (min - 1));
}
public void result()
{
System.out.println("Cracked Password is: " + crackedPassword.toString());
}
public void incrementString(StringBuffer toCrack, int min, int max)
{
toCrack.setCharAt(0, (char) ((int) toCrack.charAt(0) + 1));
for (int i = 0; i < toCrack.length(); i++)
{
if (toCrack.charAt(i) > (char) max)
{
toCrack.setCharAt(i, (char) min);
if (toCrack.length() == i + 1)
{
toCrack.append((char) min);
}
else
{
toCrack.setCharAt(i + 1, (char) ((int) toCrack.charAt(i + 1) + 1));
}
}
}
}
public void runMulti(String text)
{
prepare(text);
double time = System.nanoTime();
doItMulti();
time = System.nanoTime() - time;
System.out.println(time / (1000000000));
result();
}
public void doItMulti()
{
int cores = Runtime.getRuntime().availableProcessors();
ArrayList<Future<?>> tasks ; // How do I make my ArrayList Thread-Safe? Another approach to problem in Java?
// https://stackoverflow.com/questions/2444005/how-do-i-make-my-arraylist-thread-safe-another-approach-to-problem-in-java
tasks = (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores));
// ArrayList<Future<?>> tasks = new ArrayList<>(cores);
ExecutorService executor = Executors.newFixedThreadPool(cores);
final long step = 2000;
for (long i = 0; i < Long.MAX_VALUE; i += step)
{
while(tasks.size() > cores)
{
for(int w = 0; w < tasks.size();w++)
{
if(tasks.get(w).isDone())
{
tasks.remove(w);
break;
}
}
try
{
Thread.sleep(0);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
{
final long j = i;
if (passwordFound == false)
{
tasks.add(executor.submit(new Runnable()
{
public void run()
{
long border = j + step;
StringBuffer toCrack = new StringBuffer(10);
toCrack.append(constructString3(j, min, max));
for (long k = j; k < border; k++)
{
incrementString(toCrack, min, max);
boolean found = toCrack.toString().equals(passwordToCrack);
if (found)
{
crackedPassword = toCrack;
passwordFound = found;
break;
}
}
}
}));
}
else
{
break;
}
}
}
executor.shutdownNow();
}
public String constructString3(long number, long min, long max)
{
StringBuffer text = new StringBuffer();
if (number > Long.MAX_VALUE - min)
{
number = Long.MAX_VALUE - min;
}
ArrayList<Long> vector = new ArrayList<Long>(10);
vector.add(min - 1 + number);
long range = max - min + 1;
boolean nextLetter = false;
for (int i = 0; i < vector.size(); i++)
{
long nextLetterCounter = 0;
while (vector.get(i) > max)
{
nextLetter = true;
long multiplicator = Math.abs(vector.get(i) / range);
if ((vector.get(i) - (multiplicator * range)) < min)
{
multiplicator -= 1;
}
vector.set(i, vector.get(i) - (multiplicator * range));
nextLetterCounter += multiplicator;
}
if (nextLetter)
{
vector.add((long) (min + nextLetterCounter - 1));
nextLetter = false;
}
text.append((char) vector.get(i).intValue());
}
return text.toString();
}
}
Many thanks in advance !
The issue that you're seeing is with this line:
tasks = (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores));
Collections.synchronizedList doesn't return an ArrayList; it returns some subclass of List - java.util.Collections$SynchronizedRandomAccessList to be exact - and I don't know anything about that class other than it's a List, but it's not an ArrayList.
The easy solution to this is to declare tasks to be a List<Future<?>>:
List<Future<?>> tasks =
Collections.synchronizedList(new ArrayList<Future<?>>(cores));
Dear community members thanks you for your comments. It seems that now my safe-thread list is working. For the people who interesting in solution I will submit the resolved code below. Also, probably I should mention that I rename task
to futures, please pay attention. Once again everybody thanks !
package bfpasswrd_multi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class PasswordCracker
{
String passwordToCrack;
public boolean passwordFound;
int min;
int max;
StringBuffer crackedPassword;
public void prepare(String text)
{
passwordToCrack = text;
passwordFound = false;
min = 48;
max = 57; // http://ascii.cl/
crackedPassword = new StringBuffer();
crackedPassword.append((char) (min - 1));
}
public void result()
{
System.out.println("Cracked Password is: " + crackedPassword.toString());
}
public void incrementString(StringBuffer toCrack, int min, int max)
{
toCrack.setCharAt(0, (char) ((int) toCrack.charAt(0) + 1));
for (int i = 0; i < toCrack.length(); i++)
{
if (toCrack.charAt(i) > (char) max)
{
toCrack.setCharAt(i, (char) min);
if (toCrack.length() == i + 1)
{
toCrack.append((char) min);
}
else
{
toCrack.setCharAt(i + 1, (char) ((int) toCrack.charAt(i + 1) + 1));
}
}
}
}
public void runMulti(String text)
{
prepare(text);
double time = System.nanoTime();
doItMulti();
time = System.nanoTime() - time;
System.out.println(time / (1000000000));
result();
}
public void doItMulti()
{
int cores = Runtime.getRuntime().availableProcessors();
// ArrayList<Future<?>> task; // HOW IT WAS
//
// tasks = (ArrayList<Future<?>>) Collections.synchronizedList(new ArrayList<Future<?>>(cores)); // HOW IT WAS
List<Future<?>> futures ; // THE SOLUTION
futures = Collections.synchronizedList(new ArrayList<Future<?>>(cores)); // THE SOLUTION
// ArrayList<Future<?>> tasks = new ArrayList<>(cores);
ExecutorService executor = Executors.newFixedThreadPool(cores);
final long step = 2000;
for (long i = 0; i < Long.MAX_VALUE; i += step)
{
while(futures.size() > cores)
{
for(int w = 0; w < futures.size();w++)
{
if(futures.get(w).isDone())
{
futures.remove(w);
break;
}
}
try
{
Thread.sleep(0);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
{
final long j = i;
if (passwordFound == false)
{
futures.add(executor.submit(new Runnable()
{
public void run()
{
long border = j + step;
StringBuffer toCrack = new StringBuffer(10);
toCrack.append(constructString3(j, min, max));
for (long k = j; k < border; k++)
{
incrementString(toCrack, min, max);
boolean found = toCrack.toString().equals(passwordToCrack);
if (found)
{
crackedPassword = toCrack;
passwordFound = found;
break;
}
}
}
}));
}
else
{
break;
}
}
}
executor.shutdownNow();
}
public String constructString3(long number, long min, long max)
{
StringBuffer text = new StringBuffer();
if (number > Long.MAX_VALUE - min)
{
number = Long.MAX_VALUE - min;
}
ArrayList<Long> vector = new ArrayList<Long>(10);
vector.add(min - 1 + number);
long range = max - min + 1;
boolean nextLetter = false;
for (int i = 0; i < vector.size(); i++)
{
long nextLetterCounter = 0;
while (vector.get(i) > max)
{
nextLetter = true;
long multiplicator = Math.abs(vector.get(i) / range);
if ((vector.get(i) - (multiplicator * range)) < min)
{
multiplicator -= 1;
}
vector.set(i, vector.get(i) - (multiplicator * range));
nextLetterCounter += multiplicator;
}
if (nextLetter)
{
vector.add((long) (min + nextLetterCounter - 1));
nextLetter = false;
}
text.append((char) vector.get(i).intValue());
}
return text.toString();
}
}
I have a question.
I have 10000 strings and I want to perform some operation on each of them. I would like to parallelize this operations in order to make the total execution time acceptable.
I decided to create the thread. In particular, every 10 strings I launch 10 threads. For every threads I save the result in a list.
I have tried two versions of my code. This is my first version.
int size = 10000;
int cont = 0;
int n = 1;
String[] arrstr2;
int threadgroup = 10;
if (cont + threadgroup - 1 > size) {
arrstr2[i - cont] = subject.toString();
} else {
arrstr2[i - cont] = subject.toString();
}
if ((i == (threadgroup * n) - 1) || (i == size - 1)) {
cont = i + 1;
n = n + 1;
for (int j = 0; j < arrstr2.length; j++) {
Thread t = new Thread(new MyThread(arrstr2[j], l));
t.start();
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (cont + threadgroup - 1 > size) {
arrstr2 = new String[size - i - 1];
}
}
i = i + 1;
In this version I don't get an advantages in the total execution.
This is my second version:
int size = 10000;
int cont = 0;
int n = 1;
String[] arrstr2;
int threadgroup = 10;
if (cont + threadgroup - 1 > size) {
arrstr2[i - cont] = subject.toString();
} else {
arrstr2[i - cont] = subject.toString();
}
if ((i == (threadgroup * n) - 1) || (i == size - 1)) {
cont = i + 1;
n = n + 1;
for (int j = 0; j < arrstr2.length; j++) {
Thread t = new Thread(new MyThread(arrstr2[j], l));
t.start();
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (cont + threadgroup - 1 > size) {
arrstr2 = new String[size - i - 1];
}
}
i = i + 1;
In this case I lose some information.
MyThread is a class that does some processing and puts the result in a list java:
public class MyThread implements Runnable{
String subject;
private List<String[]> l;
public MyThread(String subject, List<String[]> l) {
this.subject = subject;
this.l = l;
}
#Override
public void run() {
synchronized (l){
//do something
String[] result = new String[2];
result[0] = res0;
result[1] = res1;
l.add(result);
}
}
For my goal, this code is correct? How can I launch a group of thread in Java Code and to retrieve an acceptable time?
Here's a little example with an ExecutorService. The thread size is fixed to 10, but your can adjust it to your needs.
The StringTask basically reverses the given string.
public class Test {
private static final int THREADS = 10;
private static final int DATA_SIZE = 1000;
public static void main(String[] args) {
// Declare a new ExecutorService with a maximum of 2 threads.
ExecutorService service = Executors.newFixedThreadPool(THREADS);
// Prepare a list of Future results.
List<Future<String>> futures = new ArrayList<Future<String>>(DATA_SIZE);
// Submit the tasks and store the results.
for (int i = 0; i < DATA_SIZE; i++) {
futures.add(service.submit(new StringTask("Sample String " + i)));
}
// Accept no new tasks.
service.shutdown();
// Retrieve the actual String results.
List<String> results = new ArrayList<String>(DATA_SIZE);
try {
for (Future<String> future : futures) {
// The get() method blocks if the execution of the task is not finished.
results.add(future.get());
System.out.println(future.get());
}
} catch (ExecutionException ee) {
System.out.println("Error while getting result!");
ee.printStackTrace();
} catch (InterruptedException ie) {
System.out.println("Error while getting result!");
ie.printStackTrace();
}
}
/**
* Callable task that reverses a given String.
*/
private static final class StringTask implements Callable<String> {
private String input;
private StringTask(String input) {
super();
if (input == null) {
throw new NullPointerException();
}
this.input = input;
}
#Override
public String call() throws Exception {
StringBuilder builder = new StringBuilder();
for (int i = this.input.length() - 1; i >= 0; i--) {
builder.append(this.input.charAt(i));
}
return builder.toString();
}
}
}
I use a Callable here instead of a Runnable because the Callable allows the task to actually return a result that we can use (through the Future interface). If you only need a task executed, you can simply use a Runnable!
Maybe you might take a look at the new Java 8 Stream API.
http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
There you can easily parallelize such operations.
Using Java 8:
List<String> res = Arrays.toStream(arrstr2)
.parallel()
.map(s -> doWork(s))
.collect(Collectors.toList());
I am trying to understand the utilities in java.util.concurrent package and learnt that we can submit callable objects to the ExecutorService, which returns Future, which is filled with the value returned by the callable, after successful completion of task within call() method.
I am understanding that all the callables are executed concurrently using multiple threads.
When I wanted to see how much improvement ExecutorService gives over the batch task execution, i thought of capturing time.
Following is the code which i tried to execute -
package concurrency;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorExample {
private static Callable<String> callable = new Callable<String>() {
#Override
public String call() throws Exception {
StringBuilder builder = new StringBuilder();
for(int i=0; i<5; i++) {
builder.append(i);
}
return builder.toString();
}
};
public static void main(String [] args) {
long start = System.currentTimeMillis();
ExecutorService service = Executors.newFixedThreadPool(5);
List<Future<String>> futures = new ArrayList<Future<String>>();
for(int i=0; i<5; i++) {
Future<String> value = service.submit(callable);
futures.add(value);
}
for(Future<String> f : futures) {
try {
System.out.println(f.isDone() + " " + f.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("Executer callable time - " + (end - start));
service.shutdown();
start = System.currentTimeMillis();
for(int i=0; i<5; i++) {
StringBuilder builder = new StringBuilder();
for(int j=0; j<5; j++) {
builder.append(j);
}
System.out.println(builder.toString());
}
end = System.currentTimeMillis();
System.out.println("Normal time - " + (end - start));
}
}
and here is the output of this -
true 01234
true 01234
true 01234
true 01234
true 01234
Executer callable time - 5
01234
01234
01234
01234
01234
Normal time - 0
Please let me know if I am missing something OR understanding something in a wrong way.
Thanks in advance for your time and help for this thread.
If you task in Callable is to small, you won't get benefits from concurrency due task switching and overhead for initialisation. Try to add more heavier loop in callable, say 1000000 iterations, and you can see difference
When you run any code esp for the first time, it takes time. If you pass a task to another thread it can take 1-10 micro-seconds and if your task take less time than this, the overhead can be greater than the benefit. i.e. using multiple threads can be much slower than using a single thread if your overhead is high enough.
I suggest you
increase the cost of the task to 1000 iterations.
make sure the result is not discarded in the single threaded example
run both tests for at least a couple of seconds to ensure the code has warmed up.
Not an answer (but I am not sure the code will fit a comment). To expand a bit on what Peter said, there is usually a sweet spot for the size of your jobs (measured in execution time), to balance pool/queue overhead with fair work distribution among workers. The code example helps find an estimate for that sweet spot. Run on your target hardware.
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class FibonacciFork extends RecursiveTask<Long> {
private static final long serialVersionUID = 1L;
public FibonacciFork( long n) {
super();
this.n = n;
}
static ForkJoinPool fjp = new ForkJoinPool( Runtime.getRuntime().availableProcessors());
static long fibonacci0( long n) {
if ( n < 2) {
return n;
}
return fibonacci0( n - 1) + fibonacci0( n - 2);
}
static int rekLimit = 8;
private static long stealCount;
long n;
private long forkCount;
private static AtomicLong forks = new AtomicLong( 0);
public static void main( String[] args) {
int n = 45;
long times[] = getSingleThreadNanos( n);
System.out.println( "Single Thread Times complete");
for ( int r = 2; r <= n; r++) {
runWithRecursionLimit( r, n, times[ r]);
}
}
private static long[] getSingleThreadNanos( int n) {
final long times[] = new long[ n + 1];
ExecutorService es = Executors.newFixedThreadPool( Math.max( 1, Runtime.getRuntime().availableProcessors() / 2));
for ( int i = 2; i <= n; i++) {
final int arg = i;
Runnable runner = new Runnable() {
#Override
public void run() {
long start = System.nanoTime();
final int minRuntime = 1000000000;
long runUntil = start + minRuntime;
long result = fibonacci0( arg);
long end = System.nanoTime();
int ntimes = Math.max( 1, ( int) ( minRuntime / ( end - start)));
if ( ntimes > 1) {
start = System.nanoTime();
for ( int i = 0; i < ntimes; i++) {
result = fibonacci0( arg);
}
end = System.nanoTime();
}
times[ arg] = ( end - start) / ntimes;
}
};
es.execute( runner);
}
es.shutdown();
try {
es.awaitTermination( 1, TimeUnit.HOURS);
} catch ( InterruptedException e) {
System.out.println( "Single Timeout");
}
return times;
}
private static void runWithRecursionLimit( int r, int arg, long singleThreadNanos) {
rekLimit = r;
long start = System.currentTimeMillis();
long result = fibonacci( arg);
long end = System.currentTimeMillis();
// Steals zählen
long currentSteals = fjp.getStealCount();
long newSteals = currentSteals - stealCount;
stealCount = currentSteals;
long forksCount = forks.getAndSet( 0);
System.out.println( "Fib(" + arg + ")=" + result + " in " + ( end-start) + "ms, recursion limit: " + r +
" at " + ( singleThreadNanos / 1e6) + "ms, steals: " + newSteals + " forks " + forksCount);
}
static long fibonacci( final long arg) {
FibonacciFork task = new FibonacciFork( arg);
long result = fjp.invoke( task);
forks.set( task.forkCount);
return result;
}
#Override
protected Long compute() {
if ( n <= rekLimit) {
return fibonacci0( n);
}
FibonacciFork ff1 = new FibonacciFork( n-1);
FibonacciFork ff2 = new FibonacciFork( n-2);
ff1.fork();
long r2 = ff2.compute();
long r1 = ff1.join();
forkCount = ff2.forkCount + ff1.forkCount + 1;
return r1 + r2;
}
}