lundi 15 août 2011
Retourner une valeur à partir d'un Thread
L'interface Runnable existe depuis le début de la plateforme Java et permet de créer des threads. Cette interface propose la méthode run qui ne prend aucun argument et ne retourne aucune valeur. Si on doit récupérer le résultat de calcul ou de l'exécution d'un thread, il faudrait passer par une classe intermédiaire et attendre la fin du thread pour récupérer le résultat. Par exemple :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Runnable runnable = ...; | |
Thread t = new Thread(runnable); | |
t.start(); | |
t.join(); | |
String value = someMethodtoGetSavedValue() |
Depuis Java 5, cela devient encore plus facile avec l'interface Callable. Cette interface est identique à Runnable sauf qu'elle définit la méthode call().
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Callable<V> { | |
V call() throws Exception; | |
} |
Pour lancer un Callable, il faut passer l'objet Callable à un ExecutorService via la méthode submit dont voici la signature :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<T> Future<T> submit(Callable<T> task) |
Comme l'implémentation des ExecutorService exécutent généralement leurs tâches de façon asynchrone, la méthode submit ne peut pas retourner le résultat de la méthode call. Elle retourne plutôt un objet de type Future qui est paramétré par le type du résultat du callable. L'objet Future est simplement une promesse de résultat dans le futur.
La méthode get() de l'objet Future renvoie le résultat et sera bloqué jusqu'à ce que la tâche soit terminée. Cette méthode est équivalente à un join().
Imaginons un programme qui lance des objets Callable convertissant un String en majuscule. Voici le code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.grosdim.randomCallable; | |
public class CallableExample { | |
static final int NB_THREADS = 5; | |
public static class StringCallable implements Callable<String>{ | |
private String stringToUpper; | |
public StringCallable(String string){ | |
this.stringToUpper = string; | |
} | |
@Override | |
public String call() throws Exception { | |
return this.stringToUpper.toUpperCase(); | |
} | |
} | |
public static void main(String[] args) throws InterruptedException, ExecutionException{ | |
List<Future<String>> futures = new ArrayList<Future<String>>(); | |
ExecutorService executor = Executors.newFixedThreadPool(NB_THREADS); | |
String[] stringArray = {"java", "callable", "myblog", "hello world", "bonjour tout le monde", "What's going on", "etc"}; | |
for( String s : stringArray){ | |
Callable<String> callable = new StringCallable(s); | |
Future<String> future = executor.submit(callable); | |
futures.add(future); | |
} | |
for(Future<String> f : futures){ | |
String result = f.get(); | |
System.out.println(result); | |
} | |
} | |
} |
Chaque objet de type StringCallable reçoit un String en paramètre et renvoie sa conversion en majuscule via la méthode call. On passe cet objet à un ExecutorService via la méthode submit qui renvoie un objet de type Future. Pour récupérer le résultat, on utilise la méthode get().
Dans cet exemple, on a utilisé un ExecutorService pour lancer un Callable mais n'importe quel Executor fera l'affaire. Pour plus d'informations sur les Executors, je vous invite à visiter cette page.
jeudi 11 août 2011
Java 7
Après quelques années de développement (au moins 3 ans), Oracle (anciennement Sun) a finalement sorti Java7.
Je
suis actuellement en stage et je me suis demandé si ce n'était pas déjà
possible d'intégrer les nouvelles fonctionalités de Java 7 dans mon
projet. Opération risquée vu que je travaille sur Eclipse et que ce
dernier est toujours en beta à l'heure où j'écris cet article : http://wiki.eclipse.org/JDT_Core/Java7.
Donc,
j'ai décidé de tester les nouvelles fonctionalités du langage avec
NetBeans qui supporte déjà toutes les fonctionalités de Java7.
Donc, commencez par télécharger NetBeans.
Avant de parler des nouvelles fonctionalités du langage, j'aimerais aussi parler des ajouts au niveau de la plateforme :
- Le support dans la JVM de langages dynamiques, telles que Groovy, Jython, JRuby, etc. L'intérêt est de faire coexister dans la JVM plusieurs langages avec la possibilité d'invoquer dynamiquement (au Runtime) du code de ces langages dans notre programme avec invokeDynamic. Par exemple, il est possible d'invoquer invoquer du code scala ou groovy dans notre programme Java et vice-versa vu que le bytecode généré (je suppose) sera le même. J'imagine que par exemple dans un futur proche un portage de Bash sur la JVM (JBash) et exécuter un programme JBash sur Windows ou MacOsX.
- Une nouvelle API pour la manipulation des fichiers et une nouvelle gestion des entrées/sorties. Cette API est très intéressante et fera l'objet d'un autre article.
- Au niveau cryptographie, le support des algorithmes de type Elliptic Curve y sont ajoutés également.
- Il y'a aussi le support de nouveaux protocoles réseau tels que SCTP et Sockets Direct Protocol.
Pour une liste complète des fonctionalités, je vous invite à consulter la page dédiée au projet Java 7 : JDK7 Features.
Des apports ont aussi ajoutés au langage.
Switch sur des String
Actuellement, on pouvait faire un switch que sur des entiers et les enums. Maintenant il est possible de le faire sur des String
Possibilité de rajouter des underscores dans les entiers
Il est aussi possible de rajouter des underscores pour la lecture des chiffres assez longs. Par exemple :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int one_million = 1_000_000;
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int one_million = 1_000_000; |
Gestion automatique des ressources
Avant, pour accéder au contenu d'une ressource (File, Socket, etc), il fallait récupérer son InputStream/OutputStream dans un try-catch, accéder à son contenu et le fermer manuellement dans une clause finally. Comme ici :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void readFile(String path) {
BufferedReader buffer = null;
try {
buffer = new BufferedReader(new FileReader(path));
String line;
while( (line = buffer.readLine()) != null){
System.out.println(line);
}
} catch (FileNotFoundException fne) {
System.out.println("File Not found");
} catch(IOException ioe){
System.out.println("Read error");
} finally {
try {
if(buffer != null)
buffer.close();
} catch(IOException ioe){
System.out.println("Buffer error");
}
}
}
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void readFile(String path) { | |
BufferedReader buffer = null; | |
try { | |
buffer = new BufferedReader(new FileReader(path)); | |
String line; | |
while( (line = buffer.readLine()) != null){ | |
System.out.println(line); | |
} | |
} catch (FileNotFoundException fne) { | |
System.out.println("File Not found"); | |
} catch(IOException ioe){ | |
System.out.println("Read error"); | |
} finally { | |
try { | |
if(buffer != null) | |
buffer.close(); | |
} catch(IOException ioe){ | |
System.out.println("Buffer error"); | |
} | |
} | |
} |
Maintenant, il est possible de déclarer nos ressources dans un bloc try et sa portée se limitera à ce bloc. Une fois que ce bloc est exécuté, les ressources seront fermés automatiquement :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
try(BufferedReader buffer = new BufferedReader(new FileReader(path))){
String line;
while( (line = buffer.readLine()) != null){
System.out.println(line);
}
}
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
try(BufferedReader buffer = new BufferedReader(new FileReader(path))){ | |
String line; | |
while( (line = buffer.readLine()) != null){ | |
System.out.println(line); | |
} | |
} |
Multi-Catch
Maintenant, il est possible de rajouter plusieurs types d'exception dans un catch.
Imaginons qu'on ait ce code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
catch (IOException ex) {
logger.log(ex);
throw ex;
catch (SQLException ex) {
logger.log(ex);
throw ex;
}
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
catch (IOException ex) { | |
logger.log(ex); | |
throw ex; | |
catch (SQLException ex) { | |
logger.log(ex); | |
throw ex; | |
} |
Ce code peut être réécrit de cette façon :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
catch (IOException|SQLException ex) { | |
logger.log(ex); | |
throw ex; | |
} |
Amélioration de l'inférence de type pour la création d'instances génériques
Avant, c'était chiant de faire ça :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Map<String, Map<String, List<String>>> map = new HashMap<String, Map<String, List<String>>>();
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Map<String, Map<String, List<String>>> map = new HashMap<String, Map<String, List<String>>>(); |
Mais maintenant :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Map<String, Map<String, List<String>>> newmap = new HashMap<>();
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Map<String, Map<String, List<String>>> newmap = new HashMap<>(); |
<> est appelé le diamond operator.
Binary Litterals
Avant les nombres étaient représentés uniquement en décimal, en octal et en hexadécimal. Maintenant, il est possible de représenter des nombres binaires en mettant le préfixe '0b' devant le nombre:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Un nombre au format hexa | |
int hexa = 0x12345; | |
//Un nombre au format binaire | |
int binary = 0b01110111; |
Les langages de programmation
Libellés :
basic,
c,
c++,
cobol,
fortran,
java,
javascript,
languages,
pascal,
perl,
programming,
python,
ruby
Pays/territoire :
1 Place de l'Hôtel de ville, 75004 Paris, France
Inscription à :
Articles (Atom)