I have to create an application which simulates concurrent threads. The "server" creates a number of "threads" and stores them in a queue. Each "thread" has defined a time to finish his execution. The server polls each "thread" from the queue to do his job for 10 ms. If the thread has finished his job, it is removed from the queue. If not, it is added at the end of the queue. I used for this application PriorityQueue. The problem is that the code i wrote is not giving the expected output; a "thread" is executed until his execution time ends.
How can I solve this problem?
SimulatedThread class
public class SimulatedThread {
private int executionTime;
private Integer id;
private int executedTime;
private boolean finished;
public SimulatedThread(){
executedTime = 0;
executionTime = 0;
setFinished(false);
}
//getters and setters
}
Server class
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Random;
public class Server {
final int TIME = 10;
final int TH_NO = 10;
//priority
final int MIN_P = 1;
final int MAX_P = 100;
//execution time
final int MIN_E = 10;
final int MAX_E = 100;
private PriorityQueue<SimulatedThread> activeThreads;
public Server() {
Comparator<SimulatedThread> comparator = new SimulatedThreadComparator();
activeThreads = new PriorityQueue<SimulatedThread>(10,comparator);
}
public void createThreads(){
for( int i = 0; i < TH_NO; i++){
SimulatedThread th = new SimulatedThread();
th.setExecutionTime(generator(MAX_E, MIN_E));
th.setId(generator(MAX_P,MIN_P));
System.out.println("New thread has been created");
System.out.println(th.toString());
activeThreads.add(th);
}
}
public void executeThreads(){
while(!activeThreads.isEmpty()){
SimulatedThread th = activeThreads.poll();
if(!th.isFinished()){
try {
Thread.sleep(TIME);
th.setExecutedTime(th.getExecutedTime() + TIME);
System.out.println(th.toString());
if((th.getExecutionTime() - th.getExecutedTime()) <= 0 ){
th.setFinished(true);
} else{
activeThreads.add(th);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
activeThreads.removeAll(activeThreads);
}
private int generator(int max, int min){
Random rand = new Random();
return rand.nextInt((max - min) + 1) - min;
}
public static void main(String[] args){
Server s = new Server();
s.createThreads();
s.executeThreads();
}
EDIT
SimulatedThreadComparator class
import java.util.Comparator;
public class SimulatedThreadComparator implements Comparator<SimulatedThread> {
#Override
public int compare(SimulatedThread o1, SimulatedThread o2) {
return o1.getId().compareTo(o2.getId());
}
}
That explains it: since the priority is the ID, the last thread that was activated will return to the head of the queue, and be the next activated, until it's finished.
Perhaps you should compare the executed time instead of the ID?
Related
So I am trying to understand how Java ForkJoin framework works. The simplest thing I could think of implementing was an array sum. However my parallel implementation is 3-4 times slower than the serial implementation. I must obviously be doing something wrong, but I am not sure what.
To measure the performance, I created a set of classes and interfaces (I used Lombok annotations for generating boilerplate code).
interface Result<T> {
T getValue();
}
#AllArgsConstructor(staticName = "of")
#Value
class MeasuredResult<T> implements Result<T> {
T value;
long elapsedTimeMillis;
}
#AllArgsConstructor(staticName = "of")
class CombinedResult<T> implements Result<T> {
private final MeasuredResult<T> parallelResult;
private final MeasuredResult<T> serialResult;
public double getParallelizationFactor() {
return (double) serialResult.getElapsedTimeMillis() / parallelResult.getElapsedTimeMillis();
}
public T getParallelValue() {
return parallelResult.getValue();
}
public T getSerialValue() {
return parallelResult.getValue();
}
#Override
public T getValue() {
return getSerialValue();
}
public boolean isDifferent() {
return !isSame();
}
public boolean isSame() {
return parallelResult.getValue().equals(serialResult.getValue());
}
}
interface Parallelizable<T> {
T processParallelly();
T processSerially();
default CombinedResult<T> getResult() {
MeasuredResult<T> parallelResult = measureParallel();
MeasuredResult<T> serialResult = measureSerial();
return CombinedResult.of(parallelResult, serialResult);
}
default MeasuredResult<T> measure(Supplier<T> supplier) {
long startTime = System.currentTimeMillis();
T value = supplier.get();
long endTime = System.currentTimeMillis();
return MeasuredResult.of(value, endTime - startTime);
}
default MeasuredResult<T> measureParallel() {
return measure(this::processParallelly);
}
default MeasuredResult<T> measureSerial() {
return measure(this::processSerially);
}
}
The idea was that by implementing the Parallelizable interface, I'd define the serial and parallel versions of the code and use the getResult() function to get a CombinedResult object with the values and time measurement to unit test with. Here's my implementation of the array sum.
#AllArgsConstructor
public class ArraySum implements Parallelizable<Integer> {
private final int[] nums;
#Override
public Integer processParallelly() {
return new ParallelForkJoinImpl(0, nums.length).compute();
}
#Override
public Integer processSerially() {
int sum = 0;
for (int num : nums) {
sum += num;
}
return sum;
}
#AllArgsConstructor()
private class ParallelForkJoinImpl extends RecursiveTask<Integer> {
private static final int THRESHOLD = 1_000;
private final int start;
private final int end;
#Override
protected Integer compute() {
if (end - start <= THRESHOLD) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += nums[i];
}
return sum;
}
int mid = (start + end) / 2;
ForkJoinTask<Integer> left = new ParallelForkJoinImpl(start, mid).fork();
ForkJoinTask<Integer> right = new ParallelForkJoinImpl(mid, end).fork();
return left.join() + right.join();
}
}
}
From what I understand, calling fork() on the RecursiveTask implementation should give me a Future object as response which will block on computation when the join() function is called on it. Also use the common ForkJoinPool will automatically be used when fork() is called.
But like I said, the value for elapsedTimeMillis for the parallel implementation is 3-4 times larger than the serial implementation, and I don't know why. What did I do wrong here?
package hw1;
public class CyrideBus {
public static final int BUS_GARAGE = -1;
private int currentCapacity;
private int numStops;
private int numPassengers;
private int currentStop;
private boolean inService;
keeps track of bus stops
public CyrideBus(int givenMaxCapacity, int givenNumStops) {
currentCapacity = givenMaxCapacity;
numStops = givenNumStops;
currentStop = BUS_GARAGE;
inService = true;
}
public int getCurrentCapacity() {
return currentCapacity;
}
public int getCurrentStop() {
return currentStop;
}
public int getNumPassengers() {
return numPassengers;
}
public int getTotalRiders() {
return numPassengers + currentCapacity+ 1;
}
public boolean isInService() {
return inService;
}
public void nextStop (int peopleOff, int peopleOn) {
currentStop= (currentStop + 1)% numStops;
peopleOff = Math.max(0, peopleOff);
peopleOn = Math.max(0, peopleOn);
numPassengers -= Math.min(peopleOff, numPassengers);
int requiredCapacity = numPassengers + peopleOn;
numPassengers = Math.min(requiredCapacity, currentCapacity);
}
public void placeInService() {
inService = true;
}
public void removeFromService() {
inService = false;
}
}
trying to make a bus route program that keeps track of people on the bus at each stop. this bus route also has a bus garage. The number one issue I am having right now is that I can not get the right amount of people on my bus keep getting
for new bus with three stops, after nextStop() six times, current stop should be 2, expected 2 but was 5
for new bus with seven stops, fter nextStop() 137 times, current stop should be 3. expected 3 but was 136
and so on
I am attempting to add up
a sequence of double precision floating point numbers which are given as Strings in an
array. The addition of these numbers is carried out in a separate background thread.
Running the code calculates the sum of the array of numbers and also gives the time that
the system took to calculate this in seconds.
I am not sure how to implement synchronization and conditional synchronization to this class:
public class SerialAdder implements Adder {
private String[] values;
private double sum;
private boolean ready = false;
public void run() {
synchronized (this) {
sum = 0.0;
for (int i = 0; i < values.length; i++) {
sum = sum + Double.valueOf(values[i]);
}
ready = true;
}
}
public synchronized void setValues(String[] values) {
this.values = values;
}
public synchronized void setThreads(int threads) {
// This does nothing since this is the single-threaded version.
}
public synchronized double getSum() {
return sum;
}
}
This should not be changed but is here for reference.
public interface Adder extends Runnable {
void setValues(String[] values);
void setThreads(int threads);
double getSum();
}
This is the main
import java.io.*;
public class Main {
/**
* All this data is "statistically initialized" and hence visibility to all threads in the running application.
*/
private static final String[] DATA1 = {"1.0", "2.0", "3.0", "4.0"};
private static final String[] DATA2 = {"100000000000000000000.0", "-100000000000000000000.0", "1.0", "2.0"};
private static final String[] DATA3 = {"1.0", "2.0", "100000000000000000000.0", "-100000000000000000000.0"};
/**
* This is an Example of more complex "static initialization" that guarantees data visibility to all threads.
*/
private static final String[] DATA4;
static {
/*** TASK3: CHANGE THIS VALUE SO THAT YOUR COMPUTER TAKES SEVERAL SECONDS FOR THE SERIAL CASE ***/
final int POWER = 10;
final int N = (int)Math.pow(2, POWER);
DATA4 = new String[N];
for (int i = 0; i < N; i++) {
DATA4[i] = String.valueOf(1.0/N);
}
}
public static void main(String[] args) throws InterruptedException, IOException {
// Start the timer ...
long startTime = System.currentTimeMillis();
/*** TASK 2 - CHANGE THIS LINE TO SEE HOW THE CODE BEHAVES WITH DIFFERENT DATA INPUTS. ***/
String[] values = DATA1;
/*** TASK 3 - CHANGE THE FOLLOWING SINGLE LINE TO CHANGE TO USING A MULTITHREADED VERSION OF THE ADDER. ***/
// This is an example of "programming to an interface" ... so only a single line
// needs to be changed to change the implementation used in the rest of the code.
Adder adder = new SerialAdder(); // = MultithreaderAdder();
adder.setValues(values);
new Thread(adder).start();
System.out.println("Answer = " + adder.getSum());
// Printed answer ... stop the timer.
long endTime = System.currentTimeMillis();
// Nanoseconds to seconds ...
System.out.println("Time = " + (endTime - startTime)/1000.0 + " seconds.") ;
}
}
And the multithreaded adder:
public class MultithreadedAdder implements Adder {
public void run() {};
public void setValues(String[] values) {};
public void setThreads(int threads) {};
public double getSum() {
return 0.0;
}
}
I am using the current data {“1.0”, “2.0”, “3.0”, “4.0”} and so expect answer of 10.0 however I am getting 0.
I would suggest some simplifications:
Drop the Adder interface. Implement the Callable interface instead. It allows you to return a value.
I'd advise against the setThreads() method. Give your Callable instance to a pooled Executor.
If one of those Strings in the array does not parse as a Double your sum will fail. What do you plan to do about it? I'd have a try/catch block.
import java.util.Arrays;
import java.util.concurrent.Callable;
public class DoubleStreamAdder implements Callable<Double> {
private final String [] values;
public DoubleStreamAdder(final String [] v) {
this.values = new String[v.length];
System.arraycopy(v, 0, this.values, 0, v.length);
}
#Override
public Double call() throws Exception {
return Arrays.stream(this.values).mapToDouble(Double::valueOf).sum();
}
}
You could do all of this using Java functional programming without the classes: see the single line in my call() method. That is what you're trying to do. The less code you write, the fewer bugs you'll have. You can eliminate more than 17 lines of code by deleting your interface and the class and writing a single line of code. Much better.
Stupid question about Java basics, but I cannot beat it for days already.
I have a class with initialized data. Randomizer is here.
public class AddContract {
private Data data = new Data();
class Data {
final String CONNUM = String.valueOf(randInt());
public int randInt() {
int min = 1;
int max = 7777;
return (int) (Math.random() * max + min);
}
}
And I have another class:
public class ContractsPage {
public ContractsPage FindContractByContractNumber() {
AddContract.Data buffer = new AddContract.Data();
this.contractNumberFilter.clear();
this.contractNumberFilter.sendKeys(buffer.CONNUM);
return this;
}
}
Pls don't judge how it looks now coz I was trying many variants how to make it work.
So, I want get the same instanse of randInt in class ContractsPage as it is in class AddContract. But Object through new generates "new" rng.
tl;dr:
With random I get var=5 in Class1, I want to adress the same var=5 in Class2.
do the random oprtaions in constructor of the class and keep it in an instance variable.
public class AddContract {
private Data data = new Data();
private String bufferCONNUMStr = String.valueOf(data.randInt());
public String bufferCONNUM() {
return bufferCONNUMStr;
}
}
public class AddContract {
private Data data = new Data();
public String bufferCONNUM() {
return data.CONNUM;
}
public String bufferPURCHNUM() {
return data.PURCHASENUM;
}
class Data {
final String CONNUM = String.valueOf(randInt());
final String PURCHASENUM = String.valueOf(randInt());
public final int randInt() {
int min = 1;
int max = 7777;
return (int) (Math.random() * max + min);
}
}
}
So I'm making a die class that can create and roll a die, return the value and the size. I'm trying to figure out how to tell the program how many of them have been created so that I can have a response be different based on how many there are. IE I want the response from printDie to be Die Value: 5 if there is only one die, and Die 1 Value: 5 if there is more than one.
Here's my code so far.
package com.catalyse.die;
import java.util.Random;
public class Die
{
// instance variables
private int myDieValue;
private int myDieSides;
private Random myRandom;
// Dice Class Constructors
public Die()
{
this.myDieValue = 1;
this.myDieSides = 4;
}
public Die(int numSides)
{
if ((numSides < 4) || (numSides > 100)) {
System.out.println("Error! You cannot have more than 100 sides or less than four!");
System.exit(0);
}
else {
myDieSides = numSides;
}
}
// getter methods
public int getDieSides()
{
return myDieSides;
}
public int getDieValue()
{
return myDieValue;
}
// setter methods
private void setDieSides(int newNumSides)
{
myDieSides = newNumSides;
}
public void rollDie()
{
Random rand = new Random();
int i = (rand.nextInt(myDieSides) + 1);
myDieValue = i;
}
public void printDie(int dieNum)
{
if (dieNum == 1) {
System.out.println("Die Value: "+myDieValue);
}
else {
System.out.println("Die "+dieNum+" Value: "+myDieValue);
}
}
}
You can have static field in your class which could be incremented in the constructor always. The reason why is it should be static is because, static fields are shared by all instances of a class, thus a local copy of the field won't be created for each of the instances you create.
private static int counter = 0;
public Die()
{
counter++;
// Other stuffs
}
// Have a getter method for the counter so that you can
// get the count of instances created at any point of time
public static int getCounter() {
return counter;
}
And then you can call the above method in your calling method like this
void someMethodInAnotherClass() {
int instanceCount = Die.getCounter(); // You need to call static method using the Class name
// other stuffs.
}
Use an static member, that is a 'class' variable, not a 'instance' variable:
private static int count = 0;
In the constructor:
public Die()
{
count++;
this.myDieValue = 1;
this.myDieSides = 4;
}
And a getter:
public static int getCount() {
return count;
}
Use a static variable
public class Die{
static int dieCount = 0;
public Die(){
dieCount++;
}
}
Every time a Die object is created, the count will increase
public static void main(String[] args){
Die die1 = new Die();
Die die2 = new Die();
int count = Die.dieCount;
}
See what is my solution for counting objects in my application
import java.util.Map;
import java.util.TreeMap;
public abstract class ObjectCounter {
private static Map<String, Long> classNameCount = new TreeMap<String, Long>();
public ObjectCounter() {
String key = this.getClass().getName();
if (classNameCount.containsKey(key)) {
classNameCount.put(key, classNameCount.get(key) + 1);
} else {
classNameCount.put(key, 1L);
}
}
public static <T extends ObjectCounter> long getCount(Class<T> c) {
String key = c.getName();
if (classNameCount.containsKey(key)) {
return classNameCount.get(key);
} else {
return 0;
}
}
public static long totalObjectsCreated() {
long totalCount = 0;
for (long count : classNameCount.values()) {
totalCount += count;
}
return totalCount;
}
}
Now extends ObjectCounter class
See below
package com.omt.factory;
public class Article extends ObjectCounter {
}
Now all your other classes are extending Article classes
package com.omt.factory;
public class Bio extends Article {
}
Now here is our main class
package com.omt.factory;
public class Main {
public static void main(String... a) {
Bio b = new Bio();
Bio b1 = new Bio();
Bio b2 = new Bio();
Bio b3 = new Bio();
Bio b4 = new Bio();
com.omt.temp.Bio bio = new com.omt.temp.Bio();
// Total Objects are created
System.out.println("Total Objects Created By Application :" + ObjectCounter.totalObjectsCreated());
// Get Number Of Objects created for class.
System.out.println("[" + com.omt.temp.Bio.class.getName() + "] Objects Created :"
+ ObjectCounter.getCount(com.omt.temp.Bio.class));
System.out.println("[" + Bio.class.getName() + "] Objects Created :" + ObjectCounter.getCount(Bio.class));
System.out.println("[" + Maths.class.getName() + "] Objects Created :" + ObjectCounter.getCount(Maths.class));
}
}
From this article