I have created a static method in a PredictionUtil class which is used to generate a new list from a smaller list. Instead of just being assigned to the new variable, the new updated list is also assigned to the smaller list. I am unable to understand this problem.
The utility class:
public class PredictionUtils {
public static List<PeriodEntity> predictPeriods(List<PeriodEntity> past){
List<PeriodEntity> updated = past;
if(past == null){
return null;
}
int pastsize = past.size();
long currentcycledur = generateCurrentCycleDuration(past);
long currentperioddur = generateCurrentPeriodDuration(past);
long laststartdate = past.get(pastsize-1).getStartTimestamp();
for(int i = 1;i <= 20;i++){
updated.add(new PeriodEntity(laststartdate+(currentcycledur*i),laststartdate+(currentcycledur*i)+currentperioddur));
}
return updated;
}
public static long generateCurrentCycleDuration(List<PeriodEntity> past){
long cycleduration = 0L;
long diff;
int pastsize = past.size();
if(pastsize == 1){
return cycleduration = 2419200000L;
}
if(pastsize < 5) {
for (int i = 0; i < pastsize - 1; i++) {
diff = past.get(i + 1).getStartTimestamp() - past.get(i).getStartTimestamp();
cycleduration += diff;
}
return (cycleduration/(pastsize-1));
}else{
for (int i = pastsize-1;i >= pastsize-4;i--) {
diff = past.get(i).getStartTimestamp() - past.get(i-1).getStartTimestamp();
cycleduration += diff;
}
return (cycleduration/4);
}
}
public static long generateCurrentPeriodDuration(List<PeriodEntity> past){
long periodduration = 0L;
long diff;
int pastsize = past.size();
if(pastsize < 4){
for(int i = 0;i < pastsize;i++){
diff = past.get(i).getEndTimestamp()-past.get(i).getStartTimestamp();
periodduration += diff;
}
return (periodduration/pastsize);
}else{
for(int i = pastsize-1;i >= pastsize-4;i--){
diff = past.get(i).getEndTimestamp()-past.get(i).getStartTimestamp();
periodduration += diff;
}
return (periodduration/4);
}
}
}
Its use:
//Observable LiveData Elements
calendarViewModel.getPastPeriods().observe(getViewLifecycleOwner(), new Observer<List<PeriodEntity>>() {
#Override
public void onChanged(final List<PeriodEntity> pastperiods) {
nextPeriod = PredictionUtils.predictPeriods(pastperiods).get(pastperiods.size());
}
});
Value of the pastperiods and nextPeriod is same, why?
Instead of creating a new instance of List, you are referring to the input.
List<PeriodEntity> updated = past;
As a result, both updated and past lists are basically the same list. So whenever you are modifying updated, it also updates the past.
To avoid that, create a new ArrayList for updated and copy the existing data of past there.
List<PeriodEntity> updated = new ArrayList<>(past);
Related
I am trying to do a multi threading simulation in Java and I have managed to do it with a queue but the execution time is high, any ideas on how I could optimize this? Can using recursion save time?
The input has to be like this:
2 5 It means that there are two threads(workers) for 5 jobs
1 2 3 4 5 This is the jobs that are an integer which means the time cost of processing that job so the output will be this:
0 0 The two threads try to simultaneously take jobs from the list, so thread with index 0 actually
1 0 takes the first job and starts working on it at the moment 0
0 1 After 1 second, thread 0 is done with the first job and takes the third job from the list, and starts processing it immediately at time 1.
1 2 One second later, thread 1 is done with the second job and takes the fourth job from the list, and starts processing it immediately at time 2
0 4 Finally, after 2 more seconds, thread 0 is done with the third job and takes the fifth job from the list, and starts processing it immediately at time 4
This is the code:
import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.StringTokenizer;
public class JobQueue {
private int numWorkers;
private int[] jobs;
private int[] assignedWorker;
private long[] startTime;
private FastScanner in;
private PrintWriter out;
public static void main(String[] args) throws IOException {
new JobQueue().solve();
}
private void readData() throws IOException {
numWorkers = in.nextInt();
int m = in.nextInt();
jobs = new int[m];
for (int i = 0; i < m; ++i) {
jobs[i] = in.nextInt();
}
}
private void writeResponse() {
for (int i = 0; i < jobs.length; ++i) {
out.println(assignedWorker[i] + " " + startTime[i]);
}
}
private void assignJobs() {
// TODO: replace this code with a faster algorithm.
assignedWorker = new int[jobs.length];
startTime = new long[jobs.length];
PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Integer>();
HashMap<Integer, Set<Integer>> workersReadyAtTimeT = new HashMap<Integer,Set<Integer>>();
long[] nextFreeTime = new long[numWorkers];
int duration = 0;
int bestWorker = 0;
for (int i = 0; i < jobs.length; i++) {
duration = jobs[i];
if(i<numWorkers) {
bestWorker = i;
nextTimesQueue.add(duration);
addToSet(workersReadyAtTimeT, duration, i,0);
}else {
int currentTime = nextTimesQueue.poll();
Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
} else {
bestWorker = workersReady.iterator().next();
workersReadyAtTimeT.remove(currentTime);
nextTimesQueue.add(currentTime+duration);
addToSet(workersReadyAtTimeT, duration, bestWorker, currentTime);
}
}
assignedWorker[i] = bestWorker;
startTime[i] = nextFreeTime[bestWorker];
nextFreeTime[bestWorker] += duration;
}
}
private void addToSet(HashMap<Integer, Set<Integer>> workersReadyAtTimeT, int duration, int worker, int current) {
if(workersReadyAtTimeT.get(current+duration)==null) {
HashSet<Integer> s = new HashSet<Integer>();
s.add(worker);
workersReadyAtTimeT.put(current+duration, s);
}else {
Set<Integer> s = workersReadyAtTimeT.get(current+duration);
s.add(worker);
workersReadyAtTimeT.put(current+duration,s);
}
}
public void solve() throws IOException {
in = new FastScanner();
out = new PrintWriter(new BufferedOutputStream(System.out));
readData();
assignJobs();
writeResponse();
out.close();
}
static class FastScanner {
private BufferedReader reader;
private StringTokenizer tokenizer;
public FastScanner() {
reader = new BufferedReader(new InputStreamReader(System.in));
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
}
It seems to me that your jobsList object is completely redundant, everything it contains is also in the jobs array and when you take the front element you get the item at jobs[i]. To speed up a little you could take the constructors of the ints out of the loop and just assign new numbers to them. Another optimization would be to not search during the first numWorkers jobs because you know you still have idle workers until you have exausted your pool. Once you have found one good worker you dont have to keep looking so you can continue out of your for-loop.
public class JobQueue {
private int numWorkers;
private int[] jobs;
private int[] assignedWorker;
private long[] startTime;
private void readData() throws IOException {
numWorkers = in.nextInt();
int m = in.nextInt();
jobs = new int[m];
for (int i = 0; i < m; ++i) {
jobs[i] = in.nextInt();
}
}
private void assignJobs() {
assignedWorker = new int[jobs.length];
startTime = new long[jobs.length];
long[] nextFreeTime = new long[numWorkers];
int duration = 0;
int bestWorker = 0;
for (int i = 0; i < jobs.length; i++) {
duration = jobs[i];
bestWorker = 0;
if (i< numWorkers){
bestWorker= i;
} else{
for (int j = 0; j < numWorkers; ++j) {
if (nextFreeTime[j] < nextFreeTime[bestWorker])
bestWorker = j;
continue;
}
}
assignedWorker[i] = bestWorker;
startTime[i] = nextFreeTime[bestWorker];
nextFreeTime[bestWorker] += duration;
}
}
However, both your solution and this slightly trimmed down one take 2 milliseconds to run. I also looked at having HashMap to maintain a NextWorker marker but at some point you catch up with it and end up looking everytime for the next one and don't win much.
You could try having an ordered List/Queue, but then you have expensive inserts instead of expensive searches, and you have to kee track of the timeslice. But a version like that could look like this:
private void assignJobs() {
assignedWorker = new int[jobs.length];
startTime = new long[jobs.length];
PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Integer>();
HashMap<Integer, Set<Integer>> workersReadyAtTimeT = new HashMap<Integer,Set<Integer>>();
long[] nextFreeTime = new long[numWorkers];
int duration = 0;
int bestWorker = 0;
for (int i = 0; i < jobs.length; i++) {
duration = jobs[i];
if(i<numWorkers) {
bestWorker = i;
nextTimesQueue.add(duration);
addToSet(workersReadyAtTimeT, duration, i,0);
}else {
int currentTime = nextTimesQueue.poll();
Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
} else {
bestWorker = workersReady.iterator().next();
workersReadyAtTimeT.remove(currentTime);
nextTimesQueue.add(currentTime+duration);
addToSet(workersReadyAtTimeT, duration, bestWorker, currentTime);
}
}
assignedWorker[i] = bestWorker;
startTime[i] = nextFreeTime[bestWorker];
nextFreeTime[bestWorker] += duration;
}
}
private void addToSet(HashMap<Integer, Set<Integer>> workersReadyAtTimeT, int duration, int worker, int current) {
if(workersReadyAtTimeT.get(current+duration)==null) {
HashSet<Integer> s = new HashSet<Integer>();
s.add(worker);
workersReadyAtTimeT.put(current+duration, s);
}else {
Set<Integer> s = workersReadyAtTimeT.get(current+duration);
s.add(worker);
workersReadyAtTimeT.put(current+duration,s);
}
}
I need to implement a "round-robin" scheduler with a job class that I cannot modify. Round-robin scheduler should process the job that has been waiting the longest first, then reset timer to zero. If two jobs have same wait time, lower id is processed first. The job class only gives three values (job id, remaining duration, and priority(which is not needed for this). each job has a start time, so only a couple of jobs may be available during first cycle, few more next cycle, etc. Since the "job array" I am calling is different every time I call it, I'm not sure how to store the wait times.
This is the job class:
public class Jobs{
private int[] stas = new int[0];
private int[] durs = new int[0];
private int[] lefs = new int[0];
private int[] pris = new int[0];
private int[] fins = new int[0];
private int clock;
public Jobs()
{
this("joblist.csv");
}
public Jobs(String filename)
{
BufferedReader fp = null;
String line = "";
String[] b = null;
int[] tmp;
try
{
fp = new BufferedReader(new FileReader(filename));
while((line = fp.readLine()) != null)
{
b = line.split(",");
if(b.length == 3)
{
try
{
int sta = Integer.parseInt(b[0]);
//System.out.println("sta: " + b[0]);
int dur = Integer.parseInt(b[1]);
//System.out.println("dur: " + b[1]);
int pri = Integer.parseInt(b[2]);
//System.out.println("pri: " + b[2]);
stas = app(stas, sta);
//System.out.println("stas: " + Arrays.toString(stas));
durs = app(durs, dur);
//System.out.println("durs: " + Arrays.toString(durs));
lefs = app(lefs, dur);
//System.out.println("lefs: " + Arrays.toString(lefs));
pris = app(pris, pri);
//System.out.println("pris: " + Arrays.toString(pris));
fins = app(fins, -1);
//System.out.println("fins: " + Arrays.toString(fins));
}
catch(NumberFormatException e) {}
}
}
fp.close();
}
catch(FileNotFoundException e) { e.printStackTrace(); }
catch(IOException e) { e.printStackTrace(); }
clock = 0;
}
public boolean done()
{
boolean done = true;
for(int i=0; done && i<lefs.length; i++)
if(lefs[i]>0) done=false;
return done;
}
public int getClock() { return clock; }
public int[][] getJobs()
{
int count = 0;
for(int i=0; i<stas.length; i++)
if(stas[i]<=clock && lefs[i]>0)
count++;
int[][] jobs = new int[count][3];
count = 0;
for(int i=0; i<stas.length; i++)
if(stas[i]<=clock && lefs[i]>0)
{
jobs[count] = new int[]{i, lefs[i], pris[i]};
count++;
}
return jobs;
}
public int cycle() { return cycle(-1); }
public int cycle(int j)
{
if(j>=0 && j<lefs.length && clock>=stas[j] && lefs[j]>0)
{
lefs[j]--;
if(lefs[j] == 0) fins[j] = clock+1;
}
clock++;
return clock;
}
private int[] app(int[] a, int b)
{
int[] tmp = new int[a.length+1];
for(int i=0; i<a.length; i++) tmp[i] = a[i];
tmp[a.length] = b;
return tmp;
}
public String report()
{
String r = "JOB,PRIORITY,START,DURATION,FINISH,DELAY,PRI*DELAY\n";
float dn=0;
float pdn=0;
for(int i=0; i<stas.length; i++)
{
if(fins[i]>=0)
{
int delay = ((fins[i]-stas[i])-durs[i]);
r+= ""+i+","+pris[i]+","+stas[i]+","+durs[i]+","+fins[i]+","+delay+","+(pris[i]*delay)+"\n";
dn+= delay;
pdn+= pris[i]*delay;
}
else
{
int delay = ((clock*10-stas[i])-durs[i]);
r+= ""+i+","+pris[i]+","+stas[i]+","+durs[i]+","+fins[i]+","+delay+","+(pris[i]*delay)+"\n";
dn+= delay;
pdn+= pris[i]*delay;
}
}
if(stas.length>0)
{
r+= "Avg,,,,,"+(dn/stas.length)+","+pdn/stas.length+"\n";
}
return r;
}
public String toString()
{
String r = "There are "+stas.length+" jobs:\n";
for(int i=0; i<stas.length; i++)
{
r+= " JOB "+i+": START="+stas[i]+" DURATION="+durs[i]+" DURATION_LEFT="+lefs[i]+" PRIORITY="+pris[i]+"\n";
}
return r;
}
I don't need full code, just an idea of how to store wait times and cycle the correct job.
While a array based solution 'may' work, I would advocate a more object oriented approach. Create 'Job' class with the desire attributes (id, start_time, wait etc). Using the csv file, create Job objects and hold them in a list. Write a comparator to sort this jobs-list (in this case based on job wait/age would be the factor).
The job executor then has to do the following:
while(jobs exist) {
iterate on the list {
if job is executable // start_time > current sys_time
consume cycles/job for executable jobs
mark completed jobs (optional)
}
remove the completed jobs
}
//\ This loop will add +1 to each job
for(int i = 0; i < jobs.length; i++)
{
waitTime[jobs[i][0]] += 1;
}
int longestWait = 0;//\ This holds value for greatest wait time
int nextJob = 0; //\ This holds value for index of job with greatest wait time
//\ this loop will check for the greatest wait time and and set variables accordingly
for(int i = 0; i < waitTime.length; i++)
{
if(waitTime[i] > longestWait)
{
longestWait = waitTime[i];
nextJob = i;
}
}
//\ this cycles the job with the highest wait time
jobsource.cycle(nextJob);
//\ this resets the wait time for processed job
waitTime[nextJob] = 0;
for a larg-DB based dynamically-multiple-area-menu, I created a class MenuPoint:
class MenuPoint{
public int areaId;
public int preID;
public String name;
public String desc;
public String stepInImg = "bsp.img";
public String stepOutImg = "bsp.img";
public String detailedForm = "bsp.fxml";
public String detailedImg = "bsp.img";
public String [] additionalOptionForm = new String[0];
public String [] additionalOptionName = new String[0];
public String [] additionalOptionImg = new String[0];}
and initialised it as an 0-length array in my main class: MenuController
public MenuPoint [] menuItem = new MenuPoint[0];
I use a API call to get my DB stored information by initialisation of MenuController.
I store the results by using the following code:
int dataStructlength = 12;
String[] exampleApiResultKeys = new String[dataStructlength];
exampleApiResultKeys[0] = "SITE_NUMBER";
exampleApiResultKeys[1] = "SITE_DESC";
exampleApiResultKeys[2] = "SITE_NUMBER_EXT";
exampleApiResultKeys[3] = "CELL_NUMBER";
exampleApiResultKeys[4] = "CELL_DESC";
exampleApiResultKeys[5] = "CELL_TYPE";
exampleApiResultKeys[6] = "MACHINE_GROUP_NUMBER";
exampleApiResultKeys[7] = "MACHINE_GROUP_DESC";
exampleApiResultKeys[8] = "MACHINE_GROUP_TYPE";
exampleApiResultKeys[9] = "STATION_NUMBER";
exampleApiResultKeys[10] = "STATION_DESC";
exampleApiResultKeys[11] = "STATION_TYPE";
exampleApiController.test_mdataGetMachineAssetStructure(exampleApiFilter, exampleApiResultKeys);
for(int i = 0; exampleApiController.resultValues.value != null && i < exampleApiController.resultValues.value.length/12; i++)
{
boolean isUseless = false;
for(int a = 0; a < dataStructlength; a ++)
if(true == exampleApiController.resultValues.value[i*dataStructlength+a].trim().isEmpty())
isUseless = true;
if(!isUseless)
{
int preId= -1;
if("M".equals(exampleApiController.resultValues.value[i*12+5]))
{
if(giveItemId(0, preId, exampleApiController.resultValues.value[i*12]) >= 0)
preId = giveItemId(0, preId, exampleApiController.resultValues.value[i*12]);
else
preId = addMenuItem(0, preId, exampleApiController.resultValues.value[i*12], exampleApiController.resultValues.value[i*12+1], "bsp.form");
}
if("M".equals(exampleApiController.resultValues.value[i*12+5]))
{
if(giveItemId(1, preId, exampleApiController.resultValues.value[i*12+3]) >= 0)
preId = giveItemId(0, preId, exampleApiController.resultValues.value[i*12+3]);
else
preId = addMenuItem(1, preId, exampleApiController.resultValues.value[i*12+3], exampleApiController.resultValues.value[i*12+4], "bsp.form");
}
if("M".equals(exampleApiController.resultValues.value[i*12+8]))
{
if(giveItemId(2, preId, exampleApiController.resultValues.value[i*12+6]) >= 0)
preId = giveItemId(0, preId, exampleApiController.resultValues.value[i*12+6]);
else
preId = addMenuItem(2, preId, exampleApiController.resultValues.value[i*12+6], exampleApiController.resultValues.value[i*12+7], "bsp.form");
}
if("M".equals(exampleApiController.resultValues.value[i*12+11]))
{
if(giveItemId(3, preId, exampleApiController.resultValues.value[i*12+9]) >= 0)
preId = giveItemId(0, preId, exampleApiController.resultValues.value[i*12+9]);
else
preId = addMenuItem(3, preId, exampleApiController.resultValues.value[i*12+9], exampleApiController.resultValues.value[i*12+10], "bsp.form");
}
}
giveItemId:
public int giveItemId(int areaId_temp, int preId_temp, String name_temp)
{
for(int i = 0; i < menuItem.length; i++)
{
if(menuItem[i].areaId == areaId_temp && menuItem[i].name.equals(name_temp) && menuItem[i].preID == preId_temp)
return i;
}
return -1;
}
addMenuItem:
public int addMenuItem(int areaId_temp, int preId_temp, String name_temp, String desc_temp, String form_temp)
{
Object newArray1 = Array.newInstance(menuItem.getClass().getComponentType(), Array.getLength(menuItem)+1); // +1 Arrayfeld
System.arraycopy(menuItem, 0, newArray1, 0, Array.getLength(menuItem));
menuItem = (MenuPoint[]) newArray1; // expend but missing attributes
menuItem[menuItem.length-1].areaId = areaId_temp;
menuItem[menuItem.length-1].preID = preId_temp;
menuItem[menuItem.length-1].name = name_temp;
menuItem[menuItem.length-1].desc = desc_temp;
menuItem[menuItem.length-1].detailedForm = form_temp;
return menuItem.length-1;
}
I found out that menuItem donsĀ“t carry any attributes after expending it.
Do I have to create "new" Instances of MenuPoint to make it work?
Is it even possible to expend a class-array without loosing attributes or their values?
It shoud, because in the end menuItem is just a pointer-array, pointing on multiple workstorage-addresses, aren't it?
Thank you guys for any tips or better concept you can give me. (I know this class-concept is silly but I have no idea for a better one)
And please excuse my bad grammar.
You create a new array in method addMenuItem which is then populated with the members from the existing menuItem, but the element at index (new) length - 1 isn't initialized:
menuItem[menuItem.length-1] = new MenuPoint();
You should have gotten a NullPointerException when trying to set the fields.
All this usage of java.lang.reflect.Array is rather contrived. There are simpler ways to achieve this. Here is a simplified versio of addMenuItem
public int addMenuItem(int areaId, String name){
MenuPoint[] newMenuItem = new MenuPoint[menuItem.length + 1];
System.arraycopy(menuItem, 0, newMenuITem, 0, menuItem.length);
menuItem = newMenuItem;
menuItem[menuItem.length-1] = new MenuPoint();
menuItem[menuItem.length-1].areaId = areaId;
menuItem[menuItem.length-1].name = name;
return menuItem.length; // Why -1 ?
}
But, above all, do use a List<MenuPoint>.
For the answer of your question Do I have to create "new" Instances of MenuPoint to make it work?
Yes
From your code snippets you need to initialize MenuPoint class object to store its values to the array menuItem.
Initialize your array element with below line
menuItem[menuItem.length-1] = new MenuPoint();
Place above line after copying your array by menuItem = (MenuPoint[]) newArray1;
Without initialization there is NullPointerException exception for setting values to null object.
There are some better ways to maintain list of object using ArrayList class.
To use ArrayList you need following code change
public List<MenuPoint> menuItem = new ArrayList<MenuPoint>; //Initialize list
Your Function will be
public int addMenuItem(int areaId_temp, int preId_temp, String name_temp, String desc_temp, String form_temp)
{
MenuPoint menuPoint = new MenuPoint();
menuPoint.areaId = areaId_temp;
menuPoint.preID = preId_temp;
menuPoint.name = name_temp;
menuPoint.desc = desc_temp;
menuPoint.detailedForm = form_temp;
menuItem.add(menuPoint);
return menuItem.size()-1;
}
I think this is easy than using reflection with array.
I am using Comb Sort to sort out a given array of Strings. The code is :-
public static int combSort(String[] input_array) {
int gap = input_array.length;
double shrink = 1.3;
int numbOfComparisons = 0;
boolean swapped=true;
//while(!swapped && gap>1){
System.out.println();
while(!(swapped && gap==1)){
gap = (int)(gap/shrink);
if(gap<1){
gap=1;
}
int i = 0;
swapped = false;
String temp = "";
while((i+gap) < input_array.length){
numbOfComparisons++;
if(Compare(input_array[i], input_array[i+gap]) == 1){
temp = input_array[i];
input_array[i] = input_array[i+gap];
input_array[i+gap] = temp;
swapped = true;
System.out.println("gap: " + gap + " i: " + i);
ArrayUtilities.printArray(input_array);
}
i++;
}
}
ArrayUtilities.printArray(input_array);
return numbOfComparisons;
}
The problem is that while it sorts many arrays , it gets stuck in an infinite loop for some arrays, particularly small arrays. Compare(input_array[i], input_array[i+gap]) is a small method that returns 1 if s1>s2, returns -1 if s1
try this version. The string array is changed to integer array (I guess you can change it back to string version). The constant 1.3 is replaced with 1.247330950103979.
public class CombSort
{
private static final int PROBLEM_SIZE = 5;
static int[] in = new int[PROBLEM_SIZE];
public static void printArr()
{
for(int i=0;i<in.length;i++)
{
System.out.print(in[i] + "\t");
}
System.out.println();
}
public static void combSort()
{
int swap, i, gap=PROBLEM_SIZE;
boolean swapped = false;
printArr();
while ((gap > 1) || swapped)
{
if (gap > 1)
{
gap = (int)( gap / 1.247330950103979);
}
swapped = false;
for (i = 0; gap + i < PROBLEM_SIZE; ++i)
{
if (in[i] - in[i + gap] > 0)
{
swap = in[i];
in[i] = in[i + gap];
in[i + gap] = swap;
swapped = true;
}
}
}
printArr();
}
public static void main(String[] args)
{
for(int i=0;i<in.length;i++)
{
in[i] = (int) (Math.random()*PROBLEM_SIZE);
}
combSort();
}
}
Please find below implementation for comb sort in java.
public static void combSort(int[] elements) {
float shrinkFactor = 1.3f;
int postion = (int) (elements.length/shrinkFactor);
do {
int cursor = postion;
for(int i=0;cursor<elements.length;i++,cursor++) {
if(elements[i]>elements[cursor]) {
int temp = elements[cursor];
elements[cursor] = elements[i];
elements[i] = temp;
}
}
postion = (int) (postion/shrinkFactor);
}while(postion>=1);
}
Please review and let me know your's feedback.
I would like to improve my fork/join little example to show that during Java Fork/Join framework execution work stealing occurs.
What changes I need to do to following code? Purpose of example: just do a linear research of a value breaking up work between multiple threads.
package com.stackoverflow.questions;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class CounterFJ<T extends Comparable<T>> extends RecursiveTask<Integer> {
private static final long serialVersionUID = 5075739389907066763L;
private List<T> _list;
private T _test;
private int _lastCount = -1;
private int _start;
private int _end;
private int _divideFactor = 4;
private static final int THRESHOLD = 20;
public CounterFJ(List<T> list, T test, int start, int end, int factor) {
_list = list;
_test = test;
_start = start;
_end = end;
_divideFactor = factor;
}
public CounterFJ(List<T> list, T test, int factor) {
this(list, test, 0, list.size(), factor);
}
#Override
protected Integer compute() {
if (_end - _start < THRESHOLD) {
int count = 0;
for (int i = _start; i < _end; i++) {
if (_list.get(i).compareTo(_test) == 0) {
count++;
}
}
_lastCount = count;
return new Integer(count);
}
LinkedList<CounterFJ<T>> taskList = new LinkedList<>();
int step = (_end - _start) / _divideFactor;
for (int j = 0; j < _divideFactor; j++) {
CounterFJ<T> task = null;
if (j == 0)
task = new CounterFJ<T>(_list, _test, _start, _start + step, _divideFactor);
else if (j == _divideFactor - 1)
task = new CounterFJ<T>(_list, _test, _start + (step * j), _end, _divideFactor);
else
task = new CounterFJ<T>(_list, _test, _start + (step * j), _start + (step * (j + 1)), _divideFactor);
// task.fork();
taskList.add(task);
}
invokeAll(taskList);
_lastCount = 0;
for (CounterFJ<T> task : taskList) {
_lastCount += task.join();
}
return new Integer(_lastCount);
}
public int getResult() {
return _lastCount;
}
public static void main(String[] args) {
LinkedList<Long> list = new LinkedList<Long>();
long range = 200;
Random r = new Random(42);
for (int i = 0; i < 1000; i++) {
list.add(new Long((long) (r.nextDouble() * range)));
}
CounterFJ<Long> counter = new CounterFJ<>(list, new Long(100), 4);
ForkJoinPool pool = new ForkJoinPool();
long time = System.currentTimeMillis();
pool.invoke(counter);
System.out.println("Fork join counter in " + (System.currentTimeMillis() - time));
System.out.println("Occurrences:" + counter.getResult());
}
}
Finally I managed how to and it's not difficult so I leave this for future readers.
In the costructor of the RecursiveTask save thread that created the instance itself. In the compute method check if executing thread is the same or not. If not work-stealing has occurred.
So I added this member variable
private long _threadId = -1;
private static int stolen_tasks = 0;
changed constructor like this:
public CounterFJ(List<T> list, T test, int start, int end, int factor) {
_list = list;
_threadId = Thread.currentThread().getId(); //added
_test = test;
_start = start;
_end = end;
_branchFactor = factor;
}
and added comparison into compute method:
#Override
protected Integer compute() {
long thisThreadId = Thread.currentThread().getId();
if (_threadId != thisThreadId){
stolen_tasks++;
}
// rest of the method