I have a list of Script that i want to execute them in parallel, i already find this way in Creating dynamic number of threads concurrently, so i use this piece of code here :
private int i;//<---------------------------------(1)
private String[] listScript = {"Script1", "Script2", "Script3", "Script4"};
private void executeQueries() throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(listScript.length);
// submit jobs to be executing by the pool
for (i = 0; i < listScript.length; i++) {
threadPool.submit(new Runnable() {
@Override
public void run() {
executeQuerie();
}
});
Thread.sleep(500);//<---------------------(2)
}
// once you've submitted your last job to the service it should be shut down
threadPool.shutdown();
// wait for the threads to finish if necessary
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}
private void executeQuerie() {
//execute scripts action
System.out.println(listScript[i]);
}
I'm really not happy with this code, i will explain a little my code so you can understand more :
(1). I use this i
variable outside the method so i can know which script i should to execute
(2). I use Thread.sleep(500);
to make sure that i execute the right script, without this i can execute the same script multiple time for example it can gives me:
Script1
Script1
Script2
Script2
My question is : how can i make sure that my scripts executed safely in parallel, should i improve this piece of code, or do you have any other safe way?
2 Answers 2
You should make i
a parameter of executeQuery :
private String[] listScript = {"Script1", "Script2", "Script3", "Script4"};
private void executeQueries() throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(listScript.length);
// submit jobs to be executing by the pool
for (int i = 0; i < listScript.length; i++) {
final int j = i;
threadPool.submit(() -> executeQuery(j));
}
// once you've submitted your last job to the service it should be shut down
threadPool.shutdown();
// wait for the threads to finish if necessary
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}
private void executeQuery(final int index) {
System.out.println(listScript[index]);
}
I used lambda here as it's simply less verbose. j
is needed as i
must be final
for the closure to work ;)
Also awaitTermination(Long.MAX_VALUE...
isn't a very good idea.... It's over 10 millions years you know ? ^^
-
\$\begingroup\$ but you can't use the
i
like you dothreadPool.submit(() -> executeQuery(i));
\$\endgroup\$Youcef LAIDANI– Youcef LAIDANI2017年06月12日 12:24:00 +00:00Commented Jun 12, 2017 at 12:24 -
\$\begingroup\$ @YCF_L yup I used another variable, I just edited my post with an added comment about this \$\endgroup\$Ronan Dhellemmes– Ronan Dhellemmes2017年06月12日 12:24:47 +00:00Commented Jun 12, 2017 at 12:24
-
\$\begingroup\$ it still the same problem :( \$\endgroup\$Youcef LAIDANI– Youcef LAIDANI2017年06月12日 12:25:16 +00:00Commented Jun 12, 2017 at 12:25
-
\$\begingroup\$ @YCF_L ??? it's working properly with
j
on my computer \$\endgroup\$Ronan Dhellemmes– Ronan Dhellemmes2017年06月12日 12:26:09 +00:00Commented Jun 12, 2017 at 12:26 -
1\$\begingroup\$ @YCF_L isn't that the point of parrallel execution ? ^^ you can use Thread.sleep if you want them to be ordered but that's not very good looking... if you want a more definitive answer, then this is a question you should check over StackOverflow \$\endgroup\$Ronan Dhellemmes– Ronan Dhellemmes2017年06月12日 12:31:18 +00:00Commented Jun 12, 2017 at 12:31
If you do not need to have control over the amount of threads used to perform the work, you could consider parallel streams and you are done with these simple lines:
private String[] listScript = {"Script1", "Script2", "Script3", "Script4"};
private void executeQueries() {
Arrays.asList(listScript).parallelStream().forEach(script -> {
System.out.println(script + " runs in thread " + Thread.currentThread());
try { Thread.sleep(5000);} catch (InterruptedException e) {}
});
}