I have run into a problem with JFugue 5.0.7: I'm coding a realtime application that plays music indefinitely, but the RealtimePlayer provided by the jfugue library mixes instruments with each other.
I have the following code
public class HelloJFugue {
public static int BPM = 150;
public static int SIGNATURE = 3;
public static boolean RANDOM = false;
public static void main(String[] args) throws MidiUnavailableException {
RealtimePlayer player = new RealtimePlayer();
BlockingQueue<Pattern> queue = new SynchronousQueue<>();
List<PatternProducer> pProducers = createPatternProducers();
Thread pConsumer = new Thread(new PatternConsumer(player, queue));
Thread pProducer = new Thread(new PatternMediator(queue, pProducers));
pConsumer.start();
pProducer.start();
}
private static List<PatternProducer> createPatternProducers() {
Random rand = new Random();
PatternProducer rightHand = new PatternProducer() {
int counter = 0;
String[] patterns = {
"Rq Rq E6i D#6i",
"E6i D#6i E6i B5i D6i C6i",
"A5q Ri C5i E5i A5i",
"B5q Ri E5i G#5i B5i",
"C6q Ri E5i E6i D#6i",
"E6i D#6i E6i B5i D6i C6i",
"A5q Ri C5i E5i A5i",
"B5q Ri E5i C6i B5i",
"A5q Ri E5i E6i D#6i"
};
#Override
public Pattern getPattern() {
Pattern p = new Pattern(patterns[RANDOM ? rand.nextInt(patterns.length - 1) + 1 : counter])
.setVoice(0)
.setInstrument("Piano");
counter++;
if (counter >= patterns.length) {
counter = 1;
}
return p;
}
};
PatternProducer leftHand = new PatternProducer() {
int counter = 0;
String[] patterns = {
"Rq Rq Rq",
"Rq Rq Rq",
"A3i E4i A4i Ri Rq",
"E3i E4i G#4i Ri Rq",
"A3i E4i A4i Ri Rq",
"Rq Rq Rq",
"A3i E4i A4i Ri Rq",
"E3i E4i G#4i Ri Rq",
"A3i E4i A4i Ri Rq"
};
#Override
public Pattern getPattern() {
Pattern p = new Pattern(patterns[RANDOM ? rand.nextInt(patterns.length - 1) + 1 : counter])
.setVoice(1)
.setInstrument("Guitar");
counter++;
if (counter >= patterns.length) {
counter = 1;
}
return p;
}
};
return new ArrayList<PatternProducer>() {
{
add(rightHand);
add(leftHand);
}
};
}
}
public class PatternMediator implements Runnable {
private BlockingQueue<Pattern> queue;
private List<PatternProducer> producers;
public PatternMediator(BlockingQueue<Pattern> queue, List<PatternProducer> producers) {
this.queue = queue;
this.producers = producers;
}
private void fillQueue() throws InterruptedException {
Pattern p = new Pattern();
for (PatternProducer producer : producers) {
p.add(producer.getPattern().setTempo(HelloJFugue.BPM));
}
this.queue.put(p);
}
#Override
public void run() {
while (true) {
try {
fillQueue();
} catch (InterruptedException ex) {
Logger.getLogger(PatternMediator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class PatternConsumer implements Runnable {
private RealtimePlayer player;
private BlockingQueue<Pattern> queue;
public PatternConsumer(RealtimePlayer player, BlockingQueue<Pattern> queue) {
this.player = player;
this.queue = queue;
}
private void playFromQueue() throws InterruptedException {
player.play(queue.take());
}
#Override
public void run() {
while (true) {
try {
playFromQueue();
Thread.sleep(HelloJFugue.SIGNATURE * 60000 / HelloJFugue.BPM);
} catch (InterruptedException ex) {
Logger.getLogger(PatternConsumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
The problem is that, when playing the two instruments (guitar and piano) get mixed, and the two cannot be played simultanously. Instead the player changes between the two instruments haphazardly, so that only one instrument, playing both patterns, can be heard at one time.
This has been resolved with the introduction of an Atom in JFugue 5.0.8. An Atom contains voice, instrument, and note information in one atomic unit, so instruments won't become disconnected from the notes they are used to play.
I describe this update more fully here: https://medium.com/#dmkoelle/whats-new-in-jfugue-5-0-8-7479abca3be4
Related
I am using Fork join pool in java for multitasking. Now i came across a situation where, for every task, I need to hit a url then wait for 10 minutes and then again hit another url to read the data. Now the problem is that for those 10 minutes my CPU is idle and not starting another tasks ( more than those defined in fork join pool).
static ForkJoinPool pool = new ForkJoinPool(10);
public static void main(String[] args){
List<String> list = new ArrayList<>();
for(int i=1; i<=100; i++){
list.add("Str"+i);
}
final Tasker task = new Tasker(list);
pool.invoke(task);
public class Tasker extends RecursiveAction{
private static final long serialVersionUID = 1L;
List<String> myList;
public Tasker(List<String> checkersList) {
super();
this.myList = checkersList;
}
#Override
protected void compute() {
if(myList.size()==1){
System.out.println(myList.get(0) + "start");
//Date start = new Date();
try {
Thread.sleep(10*60*1000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(myList.get(0) + "Finished");
}
else{
List<String> temp = new ArrayList<>();
temp.add( myList.get( myList.size()-1 ) );
myList.remove( myList.size()-1 );
Tasker left = new Tasker(myList);
Tasker right = new Tasker(temp);
left.fork();
right.compute();
left.join();
}
}
Now What should I do so that CPU picks all the tasks and then wait parallaly for them.
Unfortunately, ForkJoinPool does not work well in the face of Thread.sleep(), because it designed for many short tasks that finish quickly, rather than tasks that block for a long time.
Instead, for what you are trying to accomplish, I would recommend using ScheduledThreadPoolExecutor and dividing your task into two parts.
import java.util.*;
import java.util.concurrent.*;
public class Main {
static ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(10);
public static void main(String[] args){
for(int i=1; i<=100; i++){
pool.schedule(new FirstHalf("Str"+i), 0, TimeUnit.NANOSECONDS);
}
}
static class FirstHalf implements Runnable {
String name;
public FirstHalf(String name) {
this.name = name;
}
public void run() {
System.out.println(name + "start");
pool.schedule(new SecondHalf(name), 10, TimeUnit.MINUTES);
}
}
static class SecondHalf implements Runnable {
String name;
public SecondHalf(String name) {
this.name = name;
}
public void run() {
System.out.println(name + "Finished");
}
}
}
If Java provides a thread pool which allows releasing the underlying resources (that is, the kernel thread participating in the thread pool) during a Thread.sleep(), you should use that instead, but I currently do not know of one.
According to docs forkJoin basic use section tells:
if (my portion of the work is small enough)
do the work directly
else
split my work into two pieces
invoke the two pieces and wait for the results
Hopefully this meets your need if you are using forkjoin
public class Tasker extends RecursiveAction {
static ForkJoinPool pool = new ForkJoinPool(10);
static int threshold = 10;
public static void main(String[] args){
List<String> list = new ArrayList<>();
for(int i=1; i<=100; i++){
list.add("Str"+i);
}
final Tasker task = new Tasker(list);
pool.invoke(task);
}
private static final long serialVersionUID = 1L;
List<String> myList;
public Tasker(List<String> checkersList) {
super();
this.myList = checkersList;
}
void computeDirectly() {
for(String url : myList){
System.out.println(url + " start");
}
//Date start = new Date();
try {
//keep hitting url
while (true) {
for(String url : myList) {
//url hitting code here
System.out.println(url + " hitting");
}
Thread.sleep(10 * 60 * 1000);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(String url : myList){
System.out.println(url + " Finished");
}
}
#Override
protected void compute() {
if (myList.size() <= threshold) {
computeDirectly();
return;
}
//temp list have only one url
//List<String> temp = new ArrayList<>();
//temp.add( myList.get( myList.size()-1 ) );
//myList.remove( myList.size()-1 );
//Tasker left = new Tasker(myList);
//Tasker right = new Tasker(temp);
//left.fork();
//right.compute();
//left.join();
List<String> first = new ArrayList<>();
List<String> second = new ArrayList<>();
//divide list
int len = myList.size();
int smHalf = len / 2;//smaller half
first = myList.subList(0, smHalf);
second = myList.subList(smHalf + 1, len);
invokeAll(new Tasker(first), new Tasker(second));
}
}
I'm working on a system Reader-Writer with the Java threads, and it must be prioritized : the reader has the priority over the writer.
I wrote a source-code, which compiles and can be executed without any problem. But I would want to be really sure it's correct.
Can you tell me if you see some errors ?
Well, first I have to explain you the aim of my little program. At regular intervals, a message is displayed to the user. The latter can modify it, and change its display delay (the "interval of time"). A message is identified by an ID.
So if the user type : 0 \n Hello \n 2, it means the message n°0 is now "Hello" and will be displayed every 2 seconds.
Each message is taken care by a thread. I have to use semaphores.
SOURCE-CODES.
The reader :
public class Lecteur extends Thread {
private Message<String> message;
public Lecteur(Message<String> message) {
this.message = message;
}
public void run() {
try {
while(true) {
System.out.println(message.getContent());
int time = message.getRefresh_time()*1000;
Thread.sleep(time);
}
} catch(InterruptedException e) {
System.out.println(e);
}
}
}
The writer :
import java.util.HashMap;
import java.util.Scanner;
public class GestionnaireSaisie extends Thread {
private HashMap<Integer, Message<String>> messages;
public GestionnaireSaisie(HashMap<Integer, Message<String>> messages) {
this.messages = messages;
}
public void run() {
Scanner scanner = new Scanner(System.in);
int id;
String content;
int time_refresh;
while (true) {
id = scanner.nextInt();
content = scanner.next();
time_refresh = scanner.nextInt();
Message<String> found_msg = messages.get(id);
found_msg.setContent(content);
found_msg.setRefreshTime(time_refresh);
}
}
}
And the most interesting class, the shared object which contains shared data :
import java.util.concurrent.Semaphore;
public class Message<T> {
private static int maxid;
private int id;
private T content;
private int refresh_time;
public Semaphore mutex_content, mutex_refresh_time, semNbl;
public static int nbL = 0;
public int getId() {
return id;
}
public Message(T content, int refresh_time, Semaphore mutex_content, Semaphore mutex_refresh_time, Semaphore semNbl) {
id = maxid;
Message.maxid++;
this.content = content;
this.refresh_time = refresh_time;
this.mutex_content = mutex_content;
this.mutex_refresh_time = mutex_refresh_time;
this.semNbl = semNbl;
}
// <!-- CONTENT
public void setContent(T content) {
try {
mutex_content.acquire();
this.content = content;
mutex_content.release();
} catch(InterruptedException e) {
System.out.println(e);
}
}
public T getContent() {
T ret = null;
try {
semNbl.acquire();
Message.nbL++;
if(Message.nbL == 1) {
mutex_content.acquire();
}
semNbl.release();
ret = content;
semNbl.acquire();
Message.nbL--;
if(Message.nbL == 0) {
mutex_content.release();
}
semNbl.release();
} catch(InterruptedException e) {
System.out.println(e);
}
return ret;
}
// CONTENT -->
// <!-- REFRESH TIME
public void setRefreshTime(int refresh_time) {
try {
mutex_refresh_time.acquire();
this.refresh_time = refresh_time;
mutex_refresh_time.release();
} catch(InterruptedException e) {
System.out.println(e);
}
}
public int getRefresh_time() {
int ret = 0;
try {
semNbl.acquire();
Message.nbL++;
if(Message.nbL == 1) {
mutex_refresh_time.acquire();
}
semNbl.release();
ret = refresh_time;
semNbl.acquire();
Message.nbL--;
if(Message.nbL == 0) {
mutex_refresh_time.release();
}
semNbl.release();
} catch(InterruptedException e) {
System.out.println(e);
}
return ret;
}
// REFRESH TIME -->
}
Here some code to test it :
Semaphore mutex_content = new Semaphore(1);
Semaphore mutex_refresh_time = new Semaphore(1);
Semaphore semNbl = new Semaphore(1);
Message<String> message1 = new Message<String>("Bonjour le monde !", 5, mutex_content, mutex_refresh_time, semNbl);
new Lecteur(message1).start();
HashMap<Integer, Message<String>> messages = new HashMap<Integer, Message<String>>();
messages.put(message1.getId(), message1);
GestionnaireSaisie gs = new GestionnaireSaisie(messages);
gs.start();
I am expecting 5 results i.e. 1, 2, 3, 4, 5 yet I am getting far more? can someone please help me understand semaphores? surely as each thread calls the run method using "start", it should add 1
to the int aNumber and then print aNumber.
I don't understand why I get more than five results.
// mainClass creates Semaphore, so Copier class no longer needed
import java.util.concurrent.Semaphore;
public class mainClass {
public static void main(String[] args) throws InterruptedException {
Semaphore cp1 = new Semaphore(1, true);
Worker[] workers = new Worker[5];
for (int x=0;x<5;x++) {
workers[x] = new Worker("w" + x, cp1);
}
for (int x=0;x<5;x++) {
workers[x].start();
}
for (int x=0;x<5;x++) {
workers[x].join();
}
}
}
import java.util.concurrent.Semaphore;
public class Worker extends Thread{
int aNumber = 0;
String myName;
Semaphore myCopier;
public Worker(String nameIn, Semaphore copierIn) {
myName = nameIn;
myCopier = copierIn;
}
public void run() {
for (int x=0;x<5;x++) {
try {
sleep((int) (Math.random() * 5000)); // do some filing
myCopier.acquire();
aNumber +=1;
//System.out.println(myName + " doing some copying");
System.out.println(aNumber);
sleep((int) (Math.random() * 1000)); // do some copying
myCopier.release();
} catch (InterruptedException e) { }
}
}
}
I could not clearly get your intention. Are you trying to use semaphores to print the nos ( 1 to 5) in sequence by each thread? In that case, you can try the below:
//mainClass creates Semaphore, so Copier class no longer needed
import java.util.concurrent.Semaphore;
public class mainClass {
public static void main(String[] args) throws InterruptedException {
Semaphore cp1 = new Semaphore(1, true);
Worker[] workers = new Worker[5];
for (int x=0;x<5;x++) {
workers[x] = new Worker("w" + x, cp1, x+1);
}
for (int x=0;x<5;x++) {
workers[x].start();
}
for (int x=0;x<5;x++) {
workers[x].join();
}
}
}
class Worker extends Thread{
int aNumber = 0;
String myName;
Semaphore myCopier;
public Worker(String nameIn, Semaphore copierIn, int no) {
myName = nameIn;
myCopier = copierIn;
aNumber = no;
}
public void run() {
/*for (int x=0;x<5;x++) {*/
try {
//sleep((int) (Math.random() * 5000)); // do some filing
myCopier.acquire();
//System.out.println(myName + " doing some copying");
System.out.println("Name of the thread:" + myName + " Printed No is:" + aNumber);
//sleep((int) (Math.random() * 1000)); // do some copying
myCopier.release();
} catch (InterruptedException e) { }
//}
}
}
This is my first posting here, hope I won't seem too desperate with my question.
I have a work task which involves comparing two large set of names to see if matching exists between them (regardless of order of words in the names).
I've tried both a regular, more straightforward approach and also one using Regex.
Standard approach:
public static boolean isMatch(String terroristName, String clientName) {
String[] terroristArray = terroristName.split(" ");
String[] clientArray = clientName.split(" ");
int size = clientArray.length;
int ctrl = 0;
boolean alreadyFound = false;
for (String client : clientArray) {
for (String terrorist : terroristArray) {
//if already found a match, stop comparing with rest of the words from terrorist name
if (!alreadyFound)
if (client.compareTo(terrorist) == 0) {
alreadyFound = true;
ctrl++;
break;
}
}
alreadyFound = false;
if (ctrl == 0 && !alreadyFound) {
//if first word of client is not found in whole terrorist name
//then exit loop, no match possible
break;
}
}
if (ctrl == size)
return true;
else
return false;
}
Regex approach:
public static boolean isRegexMatch(String terroristName, String clientName) {
boolean result = false;
String[] clientNameArray = clientName.split(" ");
String myPattern = "^";
//build pattern using client name
for (String cname : clientNameArray) {
myPattern += "(?=.*\\b" + cname + "\\b)";
}
myPattern += ".*$";
Pattern pattern = Pattern.compile(myPattern);
Matcher matcher = pattern.matcher(terroristName);
// check all occurance
while (matcher.find()) {
result = true;
}
return result;
}
Loop comparing the 2 lists of names:
for (Person terrorist : terrorists) {
System.setOut(matchPrintStream);
for (Person client : clients) {
if (Util.isRegexMatch(terrorist.getNoDuplicatesName(), client.getName())) {
System.out.println(client.getId() + ";" + client.getName() + ";" + terrorist.getId() + ";" +
terrorist.getName());
}
}
}
The two sets have the following sizes:
terrorist = aprox 16000
clients = aprox 3.4 million
Runtime of both methods is quite slow:
ps -ef | grep 42810
42810 41919 99 17:47 pts/0 00:52:23 java -Xms1024M -Xmx1024M -classpath ojdbc6.jar:TerroristBuster.jar ro.btrl.mis.mihai.Main
By the time above of 00:52:23 runtime, it had processed about 170 entries, meaning it would need several days to complete. I know it has a large complexity, unsure how to lower it. What do you think of maybe using something other than List? I figured it would the most fast using foreach since of the random access.
Can this code be improved/changed in any way to improve the runtime, or am i just dealing with a too large set of data?
If you can use Java 8 this should be very easy to parallelise.
First, you don't have that many clients, so preprocess those:
final Collection<Collection<String>> processedClients = clients.parallelStream().
map(c -> c.split("\\s+")).
map(Arrays::asList).
collect(toList());
This takes each client name, splits it into the parts, and then uses the asList wrapper to turn it into a List. This is done parallelised, so should be fast.
Next we need to loop over all the terrorists:
terrorists.parallelStream().
map(t -> t.split("\\s+")).
map(t -> Stream.of(t).collect(toSet())).
forEach(t -> {
processedClients.parallelStream().forEach(c -> {
if (t.containsAll(c)) {
System.out.println("Match found t:" + t + ", c:" + c);
}
});
});
Here, for each terrorist, we split their name, but this time we turn it into a Set because Set has O(1) contains() - this means checking whether a whole client name is contained in a whole terrorist name will only take time proportional to the size of the client name.
We then use forEach to loop over the terrorists and another forEach to loop over the clients, we check is the terrorists name Set containsAll the client name.
Again this is in parallel.
In theory it shouldn't take long at all. Storing the processed client names in memory might require a bit of RAM, but it shouldn't be too much - about 1GB.
EDIT
Here is a rewrite to an earlier version (1.7, but if you remove the diamond notation it should work on 1.5)
First you need two processing classes, these are submitted to individual work threads:
final class NameProcessor implements Callable<Collection<String>> {
private final String name;
public NameProcessor(final String name) {
this.name = name;
}
#Override
public Collection<String> call() throws Exception {
return Arrays.asList(name.split("\\s+"));
}
}
final class TerroristProcessor implements Runnable {
private final String name;
public TerroristProcessor(final String name) {
this.name = name;
}
#Override
public void run() {
final Set<String> splitName = new HashSet<>(Arrays.asList(name.split("\\s+")));
for (final Collection<String> client : proccessedClients) {
if (splitName.containsAll(client)) {
System.out.println("Match found t:" + name + ", c:" + client);
}
}
}
}
Now you need to ExecutorService and an ExecutorCompletionService:
final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final ExecutorCompletionService<Collection<String>> cs = new ExecutorCompletionService<>(es);
Now you first need to process your clients, as before:
for (final String name : clients) {
cs.submit(new NameProcessor(name));
}
final Collection<Collection<String>> proccessedClients = new LinkedList<>();
for (int i = 0; i < clients.size(); ++i) {
try {
proccessedClients.add(cs.take().get());
} catch (InterruptedException ex) {
return;
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
And then process the terrorists:
final Collection<Future<?>> futures = new LinkedList<>();
for (final String terrorist : terrorists) {
futures.add(es.submit(new TerroristProcessor(terrorist)));
}
es.shutdown();
es.awaitTermination(1, TimeUnit.DAYS);
for (final Future<?> f : futures) {
try {
f.get();
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
The loop over the futures is to check for processing errors.
EDIT
The OP wants to process custom objects rather than collections of String.
I would assume you have some sort of Person class like so:
final class Person {
private final int id;
private final String name;
//constructor
//getters and setters
}
Then you can simply create a wrapper class like so:
final class PersonWrapper {
private final Person person;
private final Collection<String> processedName;
//constructor
//getters and setters
}
And create a result class like so:
final class ProblemClient {
private final Person client;
private final Person terrorist;
//constructor
//getters and setters
}
And simply rewrite the code appropriately:
final class NameProcessor implements Callable<PersonWrapper> {
private final Person person;
public NameProcessor(final Person person) {
this.person = person;
}
#Override
public PersonWrapper call() throws Exception {
return new PersonWrapper(person, Arrays.asList(person.getName().split("\\s+")));
}
}
final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final ExecutorCompletionService<PersonWrapper> cs = new ExecutorCompletionService<>(es);
for (final Person client : clients) {
cs.submit(new NameProcessor(client));
}
final Collection<PersonWrapper> proccessedClients = new LinkedList<>();
for (int i = 0; i < clients.size(); ++i) {
try {
proccessedClients.add(cs.take().get());
} catch (InterruptedException ex) {
return;
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
final class TerroristProcessor implements Runnable {
private final Person person;
private final Collection<ProblemClient> results;
public TerroristProcessor(final Person person, final Collection<ProblemClient> results) {
this.person = person;
this.results = results;
}
#Override
public void run() {
final Set<String> splitName = new HashSet<>(Arrays.asList(person.getName().split("\\s+")));
for (final PersonWrapper client : proccessedClients) {
if (splitName.containsAll(client.getProcessedName())) {
results.add(new ProblemClient(client.getPerson(), person));
}
}
}
}
final Collection<ProblemClient> results = new ConcurrentLinkedQueue<>();
final Collection<Future<?>> futures = new LinkedList<>();
for (final Person terrorist : terrorists) {
futures.add(es.submit(new TerroristProcessor(terrorist, results)));
}
es.shutdown();
es.awaitTermination(1, TimeUnit.DAYS);
for (final Future<?> f : futures) {
try {
f.get();
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
//process results
for (final ProblemClient problemClient : results) {
//whatever.
}
As I said, it might be informative to see what the outcome of preprocessing terrorists first and then looping over clients is too:
final class TerroristPreprocessor implements Callable<PersonWrapper> {
private final Person person;
public TerroristPreprocessor(final Person person) {
this.person = person;
}
#Override
public PersonWrapper call() throws Exception {
final Set<String> splitName = new HashSet<>(Arrays.asList(person.getName().split("\\s+")));
return new PersonWrapper(person, splitName);
}
}
final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final ExecutorCompletionService<PersonWrapper> cs = new ExecutorCompletionService<>(es);
for (final Person terrorist : terrorists) {
cs.submit(new TerroristPreprocessor(terrorist));
}
final Collection<PersonWrapper> proccessedTerrorists = new LinkedList<>();
for (int i = 0; i < terrorists.size(); ++i) {
try {
proccessedTerrorists.add(cs.take().get());
} catch (InterruptedException ex) {
return;
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
final class ProblemClientFinder implements Runnable {
private final Person client;
private final Collection<ProblemClient> results;
public ProblemClientFinder(final Person client, final Collection<ProblemClient> results) {
this.client = client;
this.results = results;
}
#Override
public void run() {
final Collection<String> splitName = Arrays.asList(client.getName().split("\\s+"));
for (final PersonWrapper terrorist : proccessedTerrorists) {
if (terrorist.getProcessedName().containsAll(splitName)) {
results.add(new ProblemClient(client, terrorist.getPerson()));
}
}
}
}
final Collection<ProblemClient> results = new ConcurrentLinkedQueue<>();
final Collection<Future<?>> futures = new LinkedList<>();
for (final Person client : clients) {
futures.add(es.submit(new ProblemClientFinder(client, results)));
}
es.shutdown();
es.awaitTermination(1, TimeUnit.DAYS);
for (final Future<?> f : futures) {
try {
f.get();
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
//process results
for (final ProblemClient problemClient : results) {
//whatever.
}
I tried to convert the Getting-started Akka tutorial from Scala to Java and replace actors with threads.
The tutorial can be found here http://typesafe.com/resources/tutorials/getting-started-with-akka-scala.html
The original Pi.scala file can be checked out from Typesafe giter8 template repository
g8 typesafehub/akka-first-tutorial-scala
I would like to know if what I did is correct.
And this is my Pi.java
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Pi {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Listener listener = new Listener();
//calculate(nrOfWorkers = 10, nrOfElements = 10000, nrOfMessages = 10000)
Master master = new Master(4, 1000, 1000, listener);
master.calculate();
}
}
class Worker implements Callable<Double> {
private int start;
private int nrOfElements;
public Worker(int start, int nrOfElements) {
this.start = start;
this.nrOfElements = nrOfElements;
}
#Override
public Double call() throws Exception {
double acc = 0.0;
for(int i = start; i < start + nrOfElements; i++) {
acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1);
}
return acc;
}
}
class Listener {
public void PiApproximation(double pi, long duration) {
System.out.println(String.format("\n\tPi approximation: \t\t%s\n\tCalculation time: \t%s", pi, duration));
}
}
class Master {
private double pi = 0.0;
private int nrOfResults = 0;
private final long start = java.lang.System.currentTimeMillis();
private int nrOfWorkers;
private int nrOfMessages;
private int nrOfElements;
private Listener listener;
private ExecutorService executor;
public Master(int nrOfWorkers,
int nrOfMessages,
int nrOfElements,
Listener listener) {
this.nrOfWorkers = nrOfWorkers;
this.nrOfMessages = nrOfMessages;
this.nrOfElements = nrOfElements;
this.listener = listener;
//Round robin scheduling is not enforced here as in akka.
executor = Executors.newFixedThreadPool(nrOfWorkers);
}
public void calculate() {
List<Future<Double>> list = new ArrayList<Future<Double>>();
for (int i = 0; i < nrOfMessages; i++) {
Callable<Double> worker = new Worker(i * nrOfElements, nrOfElements);
Future<Double> submit = executor.submit(worker);
list.add(submit);
}
for (Future<Double> future : list) {
try {
pi += future.get();
}
catch (InterruptedException e) { e.printStackTrace(); }
catch (ExecutionException e) { e.printStackTrace(); }
}
//send results to listener
listener.PiApproximation(pi, java.lang.System.currentTimeMillis() - start);
executor.shutdown();
}
}
There is a java version of this tutorial online also:
http://doc.akka.io/docs/akka/2.0.1/intro/getting-started-first-java.html
However, it is NOT using Threads, it is using Actors in java.
Why would you want to use Threads instad of Actors?