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;
}
}
Related
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.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I've two implementations of generating prime numbers in parallel. The core code is taken from another post here in Stackoverflow.
I'd like to know which one of these implementations is preferred and why? Also if there are better and faster solutions for this?
Implementation 1:
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class PrimeThreads {
private static int currentPrime = 0;
public static void main(String[] args) {
Object lock = new Object();
Thread primerGenThread = new Thread(() -> {
String threadName = Thread.currentThread().getName();
System.out.println("Starting thread: " + threadName);
int currentPrimeNo = 0;
synchronized (lock) {
try {
currentPrimeNo = generateNextPrime();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Prime Number Associated with this thread " + threadName + " is: " + currentPrimeNo);
System.out.println("Completed thread: " + threadName);
});
System.out.println("****This is where the project starts*****");
Scanner reader = new Scanner(System.in);
System.out.print("Enter number of threads you want to create: ");
int n = reader.nextInt();
reader.close();
ExecutorService executor = Executors.newFixedThreadPool(n);
for(int i=1;i<=n; i++) {
executor.submit(primerGenThread);
}
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("****This is where the project ends*****");
}
private static int generateNextPrime() throws InterruptedException {
long startTime = System.nanoTime();
currentPrime++;
if (currentPrime < 2) {
currentPrime = 2;
return currentPrime;
}
for (int i = 2; i < currentPrime; i++) {
if (currentPrime % i == 0) {
currentPrime++;
i = 2;
} else {
continue;
}
}
long endTime = System.nanoTime();
System.out.println("Time taken: " + (endTime - startTime) + " naoseconds.");
return currentPrime;
}
}
And implementation 2:
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class PrimeAsyncThreads {
private static int currentPrime = 0;
public static void main(String[] args) {
System.out.println("****This is where the project starts*****");
Scanner reader = new Scanner(System.in);
System.out.print("Enter number of threads you want to create: ");
int n = reader.nextInt();
reader.close();
ExecutorService executor = Executors.newFixedThreadPool(n);
for (int i = 1; i <= n; i++) {
CompletableFuture.supplyAsync(() -> {
try {
return generateNextPrime();
} catch (InterruptedException e) {
e.printStackTrace();
}
return n;
}, executor).thenAccept(s -> System.out.println("Prime Number Associated with this thread "
+ Thread.currentThread().getName() + " is: " + currentPrime));
}
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("****This is where the project ends*****");
}
private static int generateNextPrime() throws InterruptedException {
long startTime = System.nanoTime();
currentPrime++;
if (currentPrime < 2) {
currentPrime = 2;
return currentPrime;
}
for (int i = 2; i < currentPrime; i++) {
if (currentPrime % i == 0) {
currentPrime++;
i = 2;
} else {
continue;
}
}
long endTime = System.nanoTime();
System.out.println("Time taken: " + (endTime - startTime) + " naoseconds.");
return currentPrime;
}
}
Appreciate your suggestions and helps.
EDIT:
Also noticed that the second implementation does not guarantee that each thread will get a new prime. In this case sometimes multiple threads get the same value of currentPrime variable.
Thanks.
The main difference between these implementations is how they are executed.
Implempentation 1 is basically equal to a sequential execution. There is no advantage of using threads because how the synchronized block is used.
Every thread waits for the previous thread to complete before the next prime is generated.
You already noticed that Implementation 2 calculates the same prime multiple times. This is because there is no synchronization. Only the counter currentPrime is used to have some way of control which number should be considered as prime in the next thread.
Hence, both implementations are not able to calculate primes in parallel to produce a viable result.
Think about the routine. You use a value to determine if its a prime number. This value should be the input for every thread to do the calculation.
Now the only thing to consider is how to make this value thread safe to make sure it is only used once.
This can be achived, e.g. by using an Atomic variable for currentPrime.
Another improvement could be to increment currentPrime outside the generateNextPrime() method. This method could take the value as a parameter. Something like
generateNextPrime(currentPrime.incrementAndGet());
Here is a main that runs a simple counting loop three ways:
Single-threaded
2 threads using inline code that creates two distinct Thread objects
2 threads using instances of the CountingThread class that inherits from Thread
package main;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
demo();
}
public static void demo() {
final long limit = 100_000_000_000L;
long startTime = System.currenatTimeMillis();
for (long i = 0; i < limit; i++) {
// Nothing to see here, just counting
}
long endTime = System.currentTimeMillis();
System.out.println("Single threaded: Total execution time: " + (endTime - startTime) + " milliseconds.");
// Now try it in two threads. Each thread will perform 1/2 of the counting
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (long i = 0; i < limit/2; i++) {
// Nothing to see here, just counting
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (long i = limit/2; i < limit; i++) {
// Nothing to see here, just counting
}
}
});
startTime = System.currentTimeMillis();
t1.start();
t2.start();
// Join t1 until it ends, then join t2 until it ends. Note that t1 and t2 are running in parallel with this thread.
try {t1.join();} catch (InterruptedException e) {}
try {t2.join();} catch (InterruptedException e) {}
endTime = System.currentTimeMillis();
System.out.println("2 threaded using inline code: Total execution time: " + (endTime - startTime) + " milliseconds.");
// Now try it with 2 instances of the CountingThread class.
ArrayList<CountingThread> countingThreads = new ArrayList<CountingThread>();
int numberOfThreads = 2;
long increment = limit / numberOfThreads;
for (int i = 0; i < numberOfThreads; i++) {
long start, end;
start = i * increment;
end = start + increment;
countingThreads.add(new CountingThread(start, end));
}
// Launch all the threads to run in parallel
startTime = System.currentTimeMillis();
for (int i = 0; i < numberOfThreads; i++) {
countingThreads.get(i).run();
}
// Wait for all the threads to finish
for (int i = 0; i < numberOfThreads; i++) {
try {countingThreads.get(i).join();} catch(InterruptedException ex) {}
}
endTime = System.currentTimeMillis();
System.out.println(numberOfThreads + " threaded using classes: Total execution time: " + (endTime - startTime) + " milliseconds.");
}
}
Here is the class that inherits from Thread:
package main;
/**
* Count from one long int up to another long int. Really simple
*
*/
public class CountingThread extends Thread {
private long start, end;
public CountingThread(long start, long end) {
this.start = start;
this.end = end;
}
#Override
public void run() {
for(long i = start; i <= end; i++) {
}
// System.out.println("Thread counted from " + start + " to " + end);
}
}
Here is the output:
Single threaded: Total execution time: 40379 milliseconds.
2 threaded using inline code: Total execution time: 23312 milliseconds.
2 threaded using classes: Total execution time: 40358 milliseconds.
It seems like methods 2 and 3 should take about the same amount of time. What's up with that?
The machine has 4 cores.
You made a mistake and call #run instead of #start. Run method is executed in the same thread.
countingThreads.get(i).run();
So, like the question tile. I'm trying to learn multithreading programming. I have a awkward program to hlep me understand multithreading is faster than regular execution. The programm has seven classes in one java file, one test class, three classes implement Runnable, and three regular classes. The six classes all do the same thing, counting to 10 millions and return result. My problem is the three classes using three threads to run, but they didn't return the correct counts as I expected. However the three regular classes work fine.
I really appreciate anyone can help me to understand why it happens! I using JDK 9 and Eclipse 2018-12.
import java.time.Duration;
import java.time.Instant;
class MyMultiThreadExample{
public static void main(String[] args) {
GameOne g1 = new GameOne();
GameTwo g2 = new GameTwo();
GameThree g3 = new GameThree();
Thread thread1 = new Thread(g1);
Thread thread2 = new Thread(g2);
Thread thread3 = new Thread(g3);
Instant start1 = Instant.now();
thread1.start();
thread2.start();
thread3.start();
Instant end1 = Instant.now();
long elapsed = Duration.between(start1, end1).toMillis();
int total = g1.getCount() + g2.getCount() + g3.getCount();
System.out.println("MultiThread running cost " + elapsed + " to count " + total + " times");
GameFour g4 = new GameFour();
GameFive g5 = new GameFive();
GameSix g6 = new GameSix();
Instant start2 = Instant.now();
g4.run();
g5.run();
g6.run();
Instant end2 = Instant.now();
long elapsed2 = Duration.between(start2, end2).toMillis();
int total2 = g3.getCount() + g4.getCount() + g5.getCount();
System.out.println("Sequential running cost " + elapsed2 + " to count " + total2 + " times");
}
}
class GameOne implements Runnable {
int count1 = 0;
#Override
public void run() {
for (int i = 0; i < 10000000; i++) {
// System.out.print("Game1 at round " + count + " now");
count1++;
}
}
public int getCount() {
System.out.println("GameOne counts " + count1);
return count1;
}
}
class GameTwo implements Runnable {
int count2 = 0;
#Override
public void run() {
for (int i = 0; i < 10000000; i++) {
// System.out.print("Game2 at round " + count + " now");
count2++;
}
}
public int getCount() {
System.out.println("GameTwo counts " + count2);
return count2;
}
}
class GameThree implements Runnable {
int count3 = 0;
#Override
public void run() {
for (int i = 0; i < 10000000; i++) {
// System.out.print("Game3 at round " + count + " now");
count3++;
}
}
public int getCount() {
System.out.println("GameThree counts " + count3);
return count3;
}
}
class GameFour {
int count4 = 0;
public void run() {
for (int i = 0; i < 10000000; i++) {
// System.out.print("Game3 at round " + count + " now");
count4++;
}
}
public int getCount() {
System.out.println("GameFour counts " + count4);
return count4;
}
}
class GameFive {
int count5 = 0;
public void run() {
for (int i = 0; i < 10000000; i++) {
// System.out.print("Game3 at round " + count + " now");
count5++;
}
}
public int getCount() {
System.out.println("GameFive counts " + count5);
return count5;
}
}
class GameSix {
int count6 = 0;
public void run() {
for (int i = 0; i < 10000000; i++) {
// System.out.print("Game3 at round " + count + " now");
count6++;
}
}
public int getCount() {
System.out.println("GameFive counts " + count6);
return count6;
}
}
I have a awkward program to hlep me understand multithreading is faster than regular execution.
It's important to understand this is not always the case. You should only use multiple Threads when you have long running tasks that can run in parallel. IF your tasks are short, they almost certainly will run faster by running on a single Thread as there's an overhead on creating an specially synchronizing between Threads.
With that out of the way, you are not actually measuring the correct time here.
When you call Thread.start(), it will run the relevant Runnable in parallel with the code inside your function.
To let the Threads run until they complete before proceeding, you must call Thread#join():
thread1.start();
thread2.start();
thread3.start();
// all 3 Threads may be running now, but maybe not even started!
// let's wait for them to finish running by joining them
thread1.join();
thread2.join();
thread3.join();
This is the easiest way to wait... but there are others and this is a complex topic.
You may also run into trouble as your tasks have mutable state (the count variables) and the visibility of changes from different Threads needs to be carefully managed (you can make it volatile, for example, so updates are flushed to other Threads).
To learn more about concurrency in Java, I recommend you read about it. The Baeldung tutorials are excellent.
You're forgetting to call thread.join() -- this waits until the thread finishes executing.
Otherwise you're reading the counters in the middle of the execution.
Your code should be:
thread1.start()
thread2.start()
thread3.start()
thread1.join()
thread2.join()
thread3.join()
Additionally, all your classes can be compacted into a single class Game:
class Game implements Runnable {
String name;
int count = 0;
public Game(String name) {
this.name = name;
}
#Override
public void run() {
for (int i = 0; i < 10000000; i++) {
// System.out.print(name + " at round " + count + " now");
count++;
}
}
public int getCount() {
System.out.println(name + " counts " + count);
return count;
}
}
Each will have its own counter, and you can run them in a thread or in the same thread by calling run() -- your main method remains mostly unchanged except where they're instantiated. They can be instantiated like:
Game g1 = new Game("GameOne");
Game g2 = new Game("GameTwo");
Game g3 = new Game("GameThree");
Game g4 = new Game("GameFour");
Game g5 = new Game("GameFive");
Game g6 = new Game("GameSix");
I am currently making a hypothetical producer consumer problem using java. The object is to have an operating system which is 1000 bytes, but only 500 bytes available to use for threads as 500 bytes have already been consumed by drivers and other operations. The threads are as follows:
A thread to start a BubbleWitch2 session of 10 seconds, which requires 100 bytes of RAM per
second
A thread to start a Spotify stream of 20 seconds, which requires 250 bytes of RAM per second
You should also take into account the fact that the operating system is simultaneously supporting system
activity and managing the processor, memory and disk space of the device on which it is installed.
Therefore, additionally create:
System and management threads, which, together, require 50 bytes of RAM per second, and
execute for a random length of time, once invoked.
A thread to install a new security update of 2 KB, which will be stored to disk, and requires 150
bytes of RAM per second while installing. Assume sufficient disk capacity in the system to support
this thread.
The operating system has only capacity for 200 bytes per second, therefore a larger thread such as spotify will experience delays or be forced to wait. I have used code which as far as I can tell, implements this. I am also required to generate exit times which I have done with timestamps and to calculate average waiting times for threads.
I have included code in my solution for the average waiting times with system.out.print but no matter what I do, it is not actually outputting the times at all-as if they did not exist.
I am also not sure if the buffer size limitations are working as it is a matter of milliseconds-is there any way to tell if this is working from the code below?
My main method.
public class ProducerConsumerTest {
public static void main(String[] args) throws InterruptedException {
Buffer c = new Buffer();
BubbleWitch2 p1 = new BubbleWitch2(c,1);
Processor c1 = new Processor(c, 1);
Spotify p2 = new Spotify(c, 2);
SystemManagement p3 = new SystemManagement(c, 3);
SecurityUpdate p4 = new SecurityUpdate(c, 4, p1, p2, p3);
p1.setName("BubbleWitch2 ");
p2.setName("Spotify ");
p3.setName("System Management ");
p4.setName("Security Update ");
p1.setPriority(10);
p2.setPriority(10);
p3.setPriority(10);
p4.setPriority(5);
c1.start();
p1.start();
p2.start();
p3.start();
p4.start();
p2.join();
p3.join();
p4.join();
System.exit(0);
}
}
My buffer class
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* Created by Rory on 10/08/2014.
*/
class Buffer {
private int contents, count = 0, process = 0;
private boolean available = false;
private long start, end, wait, request= 0;
private DateFormat time = new SimpleDateFormat("mm:ss:SSS");
public synchronized int get() {
while (process <= 500) {
try {
wait();
} catch (InterruptedException e) {
}
}
process -= 200;
System.out.println("CPU After Process " + process);
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (process >= 1000) {
start = System.currentTimeMillis();
try {
wait();
} catch (InterruptedException e) {
}
end = System.currentTimeMillis();
wait = end - start;
count++;
request += wait;
System.out.println("Application Request Wait Time: " + time.format(wait));
process += value;
contents = value;
notifyAll();
}
}
}
My security update class
import java.lang.*;
import java.lang.System;
/**
* Created by Rory on 11/08/2014.
*/
class SecurityUpdate extends Thread {
private Buffer buffer;
private int number;
private int bytes = 150;
private int process = 0;
public SecurityUpdate(Buffer c, int number, BubbleWitch2 bubbleWitch2, Spotify spotify, SystemManagement systemManagement) throws InterruptedException {
buffer = c;
this.number = number;
bubbleWitch2.join();
spotify.join();
systemManagement.join();
}
public void run() {
for (int i = 0; i < 15; i++) {
buffer.put(i);
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1500);
} catch (InterruptedException e) {
}
}
System.out.println("-----------------------------");
System.out.println("Security Update has finished executing.");
System.out.println("------------------------------");
}
}
My processor class
class Processor extends Thread {
private Buffer processor;
private int number;
public Processor(Buffer c, int number) {
processor = c;
this.number = number;
}
public void run() {
int value = 0;
for (int i = 0; i < 60; i++) {
value = processor.get();
System.out.println("Processor #"
+ this.number
+ " got: " + value);
}
}
}
My bubblewitch class
import java.lang.*;
import java.lang.System;
import java.sql.Timestamp;
/**
* Created by Rory on 10/08/2014.
*/
class BubbleWitch2 extends Thread {
private Buffer buffer;
private int number;
private int bytes = 100;
private int duration;
public BubbleWitch2(Buffer c, int pduration) {
buffer = c;
duration = pduration;
}
long startTime = System.currentTimeMillis();
public void run() {
for (int i = 0; i < 10; i++) {
buffer.put(bytes);
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
long endTime = System.currentTimeMillis();
long timeTaken = endTime - startTime;
java.util.Date date = new java.util.Date();
System.out.println("-----------------------------");
System.out.println("BubbleWitch2 has finished executing.");
System.out.println("Time taken to execute was " +timeTaken+ " milliseconds");
System.out.println("Time Bubblewitch2 thread exited Processor was " + new Timestamp(date.getTime()));
System.out.println("-----------------------------");
}
}
My system management
class SystemManagement extends Thread {
private Buffer buffer;
private int number, min = 1, max = 15;
private int loopCount = (int) (Math.random() * (max - min));
private int bytes = 50;
private int process = 0;
public SystemManagement(Buffer c, int number) {
buffer = c;
this.number = number;
}
public void run() {
for (int i = 0; i < loopCount; i++) {
buffer.put(50);
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("-----------------------------");
System.out.println("System Management has finished executing.");
System.out.println("-----------------------------");
}
}
My spotify class
import java.sql.Timestamp;
/**
* Created by Rory on 11/08/2014.
*/
class Spotify extends Thread {
private Buffer buffer;
private int number;
private int bytes = 250;
public Spotify(Buffer c, int number) {
buffer = c;
this.number = number;
}
long startTime = System.currentTimeMillis();
public void run() {
for (int i = 0; i < 20; i++) {
buffer.put(bytes);
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
long endTime = System.currentTimeMillis();
long timeTaken = endTime - startTime;
java.util.Date date = new java.util.Date();
System.out.println(new Timestamp(date.getTime()));
System.out.println("-----------------------------");
System.out.println("Spotify has finished executing.");
System.out.println("Time taken to execute was " + timeTaken + " milliseconds");
System.out.println("Time that Spotify thread exited Processor was " + date);
System.out.println("-----------------------------");
}
}
I may need to add timestamps to one or two classes yet but does anyone have any idea how to get my average times to actually print out? Or what is preventing it and if the buffer limitation is effectively being shown here(given that we are talking about milliseconds?)
Thanks.
The reason why sys out's are not printing is because of the below condition in your buffer class:-
public synchronized void put(int value) {
while (process >= 1000) {
.....
notifyAll();
}
}
this condition never gets satisified as the process never is greater than 1000
This is the reason why your Processor thread also gets stuck because when it calls get() it finds that the process is less than 500 and hence it indefinitely waits when it reaches the wait() line of code.
Rectifying the process condition appropriately in your put should let your missing sys out get printed
public synchronized void put(int value) {
if(process <= 500) {
process+=value;
} else {
//while (process >= 1000) {
start = System.currentTimeMillis();
try {
wait();
} catch (InterruptedException e) {
}
end = System.currentTimeMillis();
wait = end - start;
count++;
request += wait;
System.out.println("Application Request Wait Time: " + time.format(wait));
process += value;
contents = value;
//}
}
notifyAll();
}
If you want securityupdate thread to always run at the last then the correct way of using join within that thread is as below:-
class SecurityUpdate extends Thread {
private Buffer buffer;
private int number;
private int bytes = 150;
private int process = 0;
private BubbleWitch2 bubbleWitch2;
private Spotify spotify;
private SystemManagement systemManagement;
public SecurityUpdate(Buffer c, int number, BubbleWitch2 bubbleWitch2, Spotify spotify, SystemManagement systemManagement) throws InterruptedException {
buffer = c;
this.number = number;
this.bubbleWitch2 = bubbleWitch2;
this.spotify = spotify;
this.systemManagement = systemManagement;
}
public void run() {
try {
bubbleWitch2.join();
spotify.join();
systemManagement.join();
} catch (InterruptedException e) {
}
System.out.println("Finally starting the security update");
for (int i = 0; i < 15; i++) {
buffer.put(bytes); // Paul check if it should be i or bytes
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1500); // Paul why is this made to sleep 1500 seconds?
} catch (InterruptedException e) {
}
}
System.out.println("-----------------------------");
System.out.println("Security Update has finished executing.");
System.out.println("------------------------------");
}
}