CS计算机代考程序代写 Java cache chain NWEN303 Concurrent Programming

NWEN303 Concurrent Programming
14: Model solutions for Ass2(universe) and Model solutions for MockTermTest
Marco Servetto VUW


Ass2 universe
Gui.java already has a minimal form of parallelism.
[..] schedulerRepaint = new ScheduledThreadPoolExecutor(1); [..] schedulerSimulation = new ScheduledThreadPoolExecutor(1);
… schedulerRepaint.scheduleAtFixedRate(()->{
if(!schedulerRepaint.getQueue().isEmpty()){..return;}
try {SwingUtilities.invokeAndWait(()->repaint());}
catch (InvocationTargetException | InterruptedException e) {..} },
500,5, TimeUnit.MILLISECONDS);

/*inside paint:*/ for(DrawableParticle p: m.pDraw){p.draw(g);} …
private void updateGraphicalRepresentation() {
ArrayList d=new ArrayList(); Color c=Color.ORANGE;
for(Particle p:this.p){//the whole ROG of d is freshly created!
d.add(new DrawableParticle((int)p.x, (int)p.y, (int)Math.sqrt(p.mass),c )); }
this.pDraw=d;//atomic update }

Ass2 universe Make model parallel
public class ModelParallel extends Model{//only override step and mergeParticles public void step() {
this.p.parallelStream().forEach(p->p.interact(this));//the most important bit this.p.parallelStream().forEach(p->p.move(this));//trivial but little gain mergeParticles();
updateGraphicalRepresentation();//do not exagerate, too much is bad
}
public void mergeParticles(){
Stack deadPs=new Stack<>();//parallelizing the line under is BAD for(Particle p:this.p){if(!p.impacting.isEmpty()){deadPs.add(p);}} this.p.removeAll(deadPs);//very hard to parallelize, and will have little gain List>newPs=new ArrayList<>();//save computations for later while(!deadPs.isEmpty()){
Particle current=deadPs.pop();
Set ps=getSingleChunck(current);//iper-hard to parallelize deadPs.removeAll(ps);
newPs.add(()->mergeParticles(ps));//add computation to do later
}
newPs.parallelStream()
.map(s->s.get())// doing mergeParticles(ps)
.sequential()//to ensure the order is correct and no need to sync this.p .forEach(p->this.p.add(p));
} }

Ass2 universe Make model parallel
public void step() { this.p.parallelStream().forEach(p->p.interact(this));//the most important bit this.p.parallelStream().forEach(p->p.move(this));//trivial but little gain mergeParticles();
updateGraphicalRepresentation();//do not exagerate, too much is bad
}

Ass2 universe Make model parallel
public void mergeParticles(){
Stack deadPs=new Stack<>();//parallelizing the line under is BAD
for(Particle p:this.p){if(!p.impacting.isEmpty()){deadPs.add(p);}} this.p.removeAll(deadPs);//very hard to parallelize, and will have little gain
List>newPs=new ArrayList<>();//save computations for later //AIM: we want to only parallelize the ‘mergeParticles(ps)’ calls while(!deadPs.isEmpty()){
Particle current=deadPs.pop();
Set ps=getSingleChunck(current); deadPs.removeAll(ps);
newPs.add(()->mergeParticles(ps));//add computation to do later }
newPs.parallelStream()
.map(s->s.get())// doing mergeParticles(ps)
.sequential()//to ensure the order is correct and no need to sync this.p .forEach(p->this.p.add(p));
}
//Ideally, we would also like to parallelize this
Set ps=getSingleChunck(current);
//but it is iper-hard and I’m not sure how much benefit can be obtained

Ass2 universe Make model parallel
newPs.parallelStream()
.map(s->s.get())// doing mergeParticles(ps)
.sequential()//to ensure the order is correct and no need to sync this.p .forEach(p->this.p.add(p));
Without the .sequential() it would be wrong in 2 different ways:
– The order of insertion would be random (so no equal behaviour)
– p is declared as
public List p=new ArrayList();
ArrayList is NOT syncronized, so adding to p from multiple workers could corrupt p.
– .sequential().forEach(..add..) is likely much faster then collecting to another list and
then doing an addAll



● ●
Ass2 universe Test correctness and speed
Do not test with the gui!
Just run a for loop with a Model and a ModelParallel;
each loop iteration do .step() on both,and then check that the two models are identical after each step.


If you add an ‘equals’ to ‘Particle’, then some operations like deadPs.removeAll(ps) will use it, possibly making the behaviour different/slower. Thus, it may be better to define your own ‘modelEqual(Model) that checks the particles one by one.
HashSet have nondeterinistic iterators, so if you want to test for equality, even between two sequential models, you must change the HashSet to LinkedHashSet or another deterministic Set.
Double/Floats may behave funny anyway; consider learning about ‘strictfp’ !!


Ass2 universe


Mock Term Test Question 1 a-b-c-d: on the handout

Mock Term Test
//The order of the for MATTERS!
//for(Image i:movie){for(Filter f:filters){}} //for(Filter f:filters){for(Image i:movie){}}
//here we assume every Image in the movie to be a different object //streams solution
void applyFiltersStreams(ArrayListfilters, ArrayList movie){ for(Filter f:filters){ //sequential for, for all the filters
movie.parallelStream().forEach(i->f.applyFilter(i));
//parallele for, for all the images
} }

Mock Term Test
//The order of the for MATTERS!
//for(Image i:movie){for(Filter f:filters){}} //for(Filter f:filters){for(Image i:movie){}}
//here we assume every Image in the movie to be a different object //futures solution
private static final ExecutorService pool=Executors.newCachedThreadPool(); void applyFiltersFut(ArrayListfilters, ArrayList movie)
throws InterruptedException, ExecutionException{ for(Filter f:filters){//for 1: start the workers
ArrayList> results = new ArrayList>();
for(Image i:movie){//just swap lines results.add(pool.submit(()->f.applyFilter(i))); }
//for 2: collect the results
for(Future r:results){r.get();} }
}

//Can still be improved!
Mock Term Test
//first streams solution
//for each Image, we parallelized the application of a single filter,
//we repeated that for all filters.
void applyFiltersStreams(ArrayListfilters, ArrayList movie){
for(Filter f:filters){ movie.parallelStream().forEach(i->f.applyFilter(i));
} }
//We show now how to parallelize the application of all //the filters at the same time.
//It is a bigger operation;
//parallelizing something bigger is better then parallelizing //something smaller.
void applyFiltersStreams(ArrayListfilters, ArrayList movie){ movie.parallelStream().forEach(i->{
for(Filter f:filters){f.applyFilter(i);}
}); }


Mock Term Test Question 2 bad code: the good version
public boolean fix(Product product){
Stream des=Stream.of(product.description);
var msgs=Stream.concat(des,product.reviews.stream()).parallel()
.filter(this::polite) .map(this::fixGrammar) .collect(Collectors.toList());
if(msgs.size()!=product.reviews.size()+1){return false;} product.description=msgs.get(0); product.reviews=msgs.subList(1,msgs.size());
return true;
}



Mock Term Test Question 2 bad code: bugs in the wrong
BUG1: Survives an InterruptedException without
stopping the computation or resetting the interrupted flag … catch (InterruptedException e) { … e.printStackTrace(); } …
BUG2: attempts to mutate the content of the reviews field, but by being a List and not an ArrayList, it may be not mutable and thus those two lines may cause a runtime exception for a valid Product instance.
productId.reviews.clear(); productId.reviews.addAll(reviews);

class ComplexCode {
public boolean polite(String s){/*..*/}
public String fixGrammar(String s){/*..*/}
//the grammar of a polite Product is fixed, and true is returned.
//if the product is not polite, false is returned and the product is not modified. public boolean fix(Product productId){
String description;
ArrayList reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(productId.reviews); String tag=new String(“###”);//created with new, have unique identity! description=productId.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity! description=product.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity! description=product.description;
ArrayList kools=new ArrayList();
for(int i=0;i reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity!
String description=product.description; ArrayList kools=new ArrayList(); for(int i=0;i reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity!
String description=product.description; ArrayList kools=new ArrayList(); for(int i=0;i reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity!
ArrayList kools=new ArrayList(); for(int i=0;i reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity!
ArrayList kools=new ArrayList(); for(int i=0;i

public boolean fix(Product product){
Question 8
ArrayList reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity!
ArrayList kools=new ArrayList(); for(int i=0;is==tag)){return false;} product.description=description; product.reviews.clear(); product.reviews.addAll(reviews);
return true; }

public boolean fix(Product product){
ArrayList kools=new ArrayList(); for(int i=0;i{
String current=reviews.get(j);
if(polite(current)){ reviews.set(j,fixGrammar(current)); } else{ reviews.set(j,tag); }
});
koolParrallel.start();
kools.add(koolParrallel);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:kools){
try { t.join(); }
catch (InterruptedException e){ e.printStackTrace(); } }
if(reviews.stream().anyMatch(s->s==tag)){return false;} product.description=description; product.reviews.clear(); product.reviews.addAll(reviews);
return true; }
Question 8 bad code: Normalization
ArrayList reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity!
We can use a lambda instead of an anonymous nested class

public boolean fix(Product product){
Question 8 bad code: Normalization
null would also be a good tag, since we know is not in the input
ArrayList reviews=new ArrayList(product.reviews); String tag=new String(“###”);//created with new, have unique identity!
ArrayList kools=new ArrayList(); for(int i=0;i{
String current=reviews.get(j);
if(polite(current)){ reviews.set(j,fixGrammar(current)); } else{ reviews.set(j,tag); }
});
koolParrallel.start();
kools.add(koolParrallel);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:kools){
try { t.join(); }
catch (InterruptedException e){ e.printStackTrace(); } }
if(reviews.stream().anyMatch(s->s==tag)){return false;} product.description=description; product.reviews.clear(); product.reviews.addAll(reviews);
return true; }

public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); ArrayList kools=new ArrayList();
for(int i=0;i{
String current=reviews.get(j);
if(polite(current)){ reviews.set(j,fixGrammar(current)); } else{ reviews.set(j,tag); }
});
koolParrallel.start();
kools.add(koolParrallel);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:kools){
try { t.join(); }
catch (InterruptedException e){ e.printStackTrace(); } }
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews.clear(); product.reviews.addAll(reviews);
return true; }
Question 8 bad code: Normalization
null would also be a good tag, since we know is not in the input

public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); ArrayList kools=new ArrayList();
for(int i=0;i{
String current=reviews.get(j);
if(polite(current)){ reviews.set(j,fixGrammar(current)); } else{ reviews.set(j,tag); }
});
koolParrallel.start();
kools.add(koolParrallel);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:kools){
try { t.join(); }
catch (InterruptedException e){ e.printStackTrace(); } }
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews.clear(); product.reviews.addAll(reviews);
return true; }
Question 8 bad code: Normalization
As discussed, clear+addAll could fail. Lets just use assignment!

public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); ArrayList kools=new ArrayList();
for(int i=0;i{
String current=reviews.get(j);
if(polite(current)){ reviews.set(j,fixGrammar(current)); } else{ reviews.set(j,tag); }
});
koolParrallel.start();
kools.add(koolParrallel);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:kools){
try { t.join(); }
catch (InterruptedException e){ e.printStackTrace(); } }
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews=reviews;
return true;
}
Question 8 bad code: Normalization
As discussed, clear+addAll could fail. Lets just use assignment!

public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); ArrayList kools=new ArrayList();
for(int i=0;i{
String current=reviews.get(j);
if(polite(current)){ reviews.set(j,fixGrammar(current)); } else{ reviews.set(j,tag); }
});
koolParrallel.start();
kools.add(koolParrallel);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:kools){
try { t.join(); }
catch (InterruptedException e){ e.printStackTrace(); } }
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews=reviews;
return true;
}
Question 8 bad code: Normalization
Terrible names

public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); ArrayList tasks=new ArrayList();
for(int i=0;i{
String current=reviews.get(j);
if(polite(current)){ reviews.set(j,fixGrammar(current)); } else{ reviews.set(j,tag); }
});
t.start();
tasks.add(t);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:tasks){
try { t.join(); }
catch (InterruptedException e){ e.printStackTrace(); } }
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews=reviews;
return true;
}
Question 8 bad code: Normalization
Terrible names

public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); ArrayList tasks=new ArrayList();
for(int i=0;i{
Question 8 bad code: Normalization
CompletableFutures instead of Thread?
String current=reviews.get(j);
if(polite(current)){ reviews.set(j,fixGrammar(current)); } else{ reviews.set(j,tag); }
});
t.start();
tasks.add(t);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:tasks){
try { t.join(); }
catch (InterruptedException e){ e.printStackTrace(); } }
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews=reviews;
return true;
}

public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); var tasks=new ArrayList<>>();
for(int i=0;i{
String current=reviews.get(j); if(polite(current)){reviews.set(j,fixGrammar(current));} else{reviews.set(j,null);}
});
tasks.add(t);
}
if(!polite(product.description)){ return false; } String description=fixGrammar(product.description); for(Thread t:tasks){ t.join(); } if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews=reviews;
return true;
}
Question 8 bad code: Normalization
CompletableFutures instead of Thread? This join does not even throw InterruptedException

Question 8 bad code: Normalization
public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); var tasks=new ArrayList<>>();
for(int i=0;i{
String current=reviews.get(j); if(polite(current)){reviews.set(j,fixGrammar(current));} else{reviews.set(j,null);}
});
tasks.add(t);
}
if(!polite(product.description)){ return false; }
String description=fixGrammar(product.description); for(Thread t:tasks){ t.join(); } if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews=reviews;
return true;
}
After those AUTOMATIC transformations the code is manageable. How to do better?

Question 8 bad code: Normalization
public boolean fix(Product product){
ArrayList reviews=new ArrayList(product.reviews); var tasks=new ArrayList<>>();
for(int i=0;i{
String current=reviews.get(j); if(polite(current)){reviews.set(j,fixGrammar(current));} else{reviews.set(j,null);}
});
tasks.add(t);
}
if(!polite(product.description)){ return false; }
String description=fixGrammar(product.description); for(Thread t:tasks){ t.join(); } if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=description; product.reviews=reviews;
return true;
}
Idea: both description and reviews are just strings, and we handle them the same. Can I just add the description as an extra review?

Question 8 bad code: Normalization
public boolean fix(Product product){
ArrayList reviews=new ArrayList<>(product.reviews+1); reviews.add(product.description);
var tasks=new ArrayList>();
for(int i=0;i{
String current=reviews.get(j); if(polite(current)){reviews.set(j,fixGrammar(current));} else{reviews.set(j,null);}
});
tasks.add(t);
}
for(var t:tasks){t.join();} if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
Now more automatic transformations are possible!!

Question 8 bad code: Normalization
public boolean fix(Product product){
ArrayList reviews=new ArrayList<>(product.reviews+1); reviews.add(product.description);
var tasks=new ArrayList>();
for(int i=0;i{
String current=reviews.get(j); if(polite(current)){reviews.set(j,fixGrammar(current));} else{reviews.set(j,null);}
});
tasks.add(t);
}
for(var t:tasks){t.join();} if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
Since we join directly after composing the list of tasks, we can use streams instead!

Question 8 bad code: Normalization
public boolean fix(Product product){
List reviews=new ArrayList<>(product.reviews+1); reviews.add(product.description); reviews=reviews.parallelStream().map(current->{
if(polite(current)){return fixGrammar(current);} else{return null;} }).collect(Collectors.toList());
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
Since we join directly after composing the list of tasks, we can use streams instead!

Question 8 bad code: Normalization
public boolean fix(Product product){
List reviews=new ArrayList<>(product.reviews+1); reviews.add(product.description); reviews=reviews.parallelStream().map(current->{
if(polite(current)){return fixGrammar(current);} else{return null;} }).collect(Collectors.toList());
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
Now we can normalize the if in the lambda

Question 8 bad code: Normalization
public boolean fix(Product product){
List reviews=new ArrayList<>(product.reviews+1); reviews.add(product.description); reviews=reviews.parallelStream().map(current->{
if(!polite(current)){return null;} return fixGrammar(current);} }).collect(Collectors.toList());
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
Now we can normalize the if in the lambda

Question 8 bad code: Normalization
public boolean fix(Product product){
List reviews=new ArrayList<>(product.reviews+1); reviews.add(product.description); reviews=reviews.parallelStream().map(current->{
if(!polite(current)){return null;} return fixGrammar(current);} }).collect(Collectors.toList());
if(reviews.stream().anyMatch(s->s==null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
we can replace anyMatch with contains(null)

Question 8 bad code: Normalization
public boolean fix(Product product){
List reviews=new ArrayList<>(product.reviews+1); reviews.add(product.description); reviews=reviews.parallelStream().map(current->{
if(!polite(current)){return null;} return fixGrammar(current);} }).collect(Collectors.toList());
if(reviews.contains(null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
we can replace anyMatch with contains(null)

Question 8 bad code: Normalization
public boolean fix(Product product){
List reviews=new ArrayList<>(product.reviews+1); reviews.add(product.description); reviews=reviews.parallelStream().map(current->{
if(!polite(current)){return null;} return fixGrammar(current);} }).collect(Collectors.toList());
if(reviews.contains(null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
Creating an ArrayList just to stream on it once is sad. Start with streams!

Question 8 bad code: Normalization
public boolean fix(Product product){
Stream data=product.reviews.stream(); data=Stream.concat(data,Stream.of(product.description)); List reviews=data.parallel().map(current->{
if(!polite(current)){return null;} return fixGrammar(current);} }).collect(Collectors.toList());
if(reviews.contains(null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
Creating an ArrayList just to stream on it once is sad. Start with streams!

Question 8 bad code: Normalization
public boolean fix(Product product){
Stream data=product.reviews.stream(); data=Stream.concat(data,Stream.of(product.description)); List reviews=data.parallel().map(current->{
if(!polite(current)){return null;} return fixGrammar(current);} }).collect(Collectors.toList());
if(reviews.contains(null)){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1); return true;
}
Collecting nulls is sad. Can we just filter them out and then check the size of the result?

Question 8 bad code: Normalization
public boolean fix(Product product){
Stream data=product.reviews.stream(); data=Stream.concat(data,Stream.of(product.description)); List reviews=data.parallel()
.filter(current->polite(current))
.map(current->fixGrammar(current))
.collect(Collectors.toList());
if(reviews.size()!=product.reviews.size()+1){return false;} product.description=reviews.get(reviews.size()-1); product.reviews=reviews.sublist(0,reviews.size()-1);
return true;
}
Collecting nulls is sad. Can we just filter them out and then check the size of the result?

Question 8 bad code: Normalization
public boolean fix(Product product){
Stream data = product.reviews.stream();
data = Stream.concat(data, Stream.of(product.description)); List reviews = data.parallel()
.filter(this::polite) .map(this::fixGrammar) .collect(Collectors.toList());
if(reviews.size()!=product.reviews.size()+1){ return false; } product.description = reviews.get(reviews.size()-1); product.reviews = reviews.sublist(0, reviews.size()-1); return true;
}
Finally, we can format this code up to a consistent personal taste.

Question 8 bad code: Normalization
//version obtained by normalization
Stream data = product.reviews.stream();
data = Stream.concat(data, Stream.of(product.description)); List reviews = data.parallel()
.filter(this::polite) .map(this::fixGrammar) .collect(Collectors.toList());
if(reviews.size()!=product.reviews.size()+1){ return false; } product.description = reviews.get(reviews.size()-1); product.reviews = reviews.sublist(0, reviews.size()-1); return true;
//model solution
Stream des=Stream.of(product.description);
var msgs=Stream.concat(des,product.reviews.stream()).parallel()
.filter(this::polite) .map(this::fixGrammar) .collect(Collectors.toList());
if(msgs.size()!=product.reviews.size()+1){return false;} product.description=msgs.get(0); product.reviews=msgs.subList(1,msgs.size());
return true;
Oh, look, the good version of the code was just hidden behind the bad version!

Question 3
Question 3a: [10]
Explain why so many methods in Java throws InterruptedException?
What is the purpose of this exception?

Question 3 Consider the following code:
public String guessPassword(){
while(true){
String result = guessOneTime();
if(result!=null){ return result; }
}
}
Doing minimal code modifications, turn guessPassword into an interruptible method.
public String guessPassword()throws InterruptedException{ while(true){
if(Thread.interrupted()){ throw new InterruptedException(); } String result = guessOneTime();
if(result!=null){ return result; }
}
}
Question 3b: [10]

● ●


Next time
More of an HelpDesk:
Prepare some questions and I will answer in the lecture.
There will be no slides, so if no one have questions I will just look at you silently for 50 mins 🙂
So, review the slides and prepare questions ! There must be a lot that I can clarify!