Visualizzazione post con etichetta java 7. Mostra tutti i post
Visualizzazione post con etichetta java 7. Mostra tutti i post

sabato 5 aprile 2014

Generazione numeri casuali

L'utilizzo della classe java.util.Random in un contesto di concorrenza può portare a dei cali di performance e a problemi di contesa delle risorse.
In ambienti multithreaded è preferibile utilizzare la classe

java.util.concurrent.ThreadLocalRandom

introdotta con la java 1.7.

Ad esempio per ottenere un numero causale tra 1 e 10 si può utilizzare il metodo nextInt(int  least,int bound)

Dove la javadoc recita: "Returns a pseudorandom, uniformly distributed value between the given least value (inclusive) and bound (exclusive)", quindi


int n=ThreadLocalRandom.current().nextInt(1, 11);
System.out.println(n);



domenica 19 gennaio 2014

Esempio utilizzo AtomicInteger

La classe AtomicInteger si trova nel package java.util.concurrent.atomic.
Si utilizza per evitare i problemi di tipo data race nel caso di operazioni multi-thread, quindi garantisce che nel caso di accessi ad un contatore una sincronizzazione sulla variabile da incrementare.
Vediamo un esempio classico di utilizzo di variabili intere in un ambiente multi thread.


package it.threads;
public class ClassicIntTest extends Thread {
 private static Integer intero=new Integer(0);
 public void run(){
  System.out.println("CLASSICO: Incremento 
                e recupero il valore "+ ++intero);
 }
}


Se lanciamo il Thread per 10 volte in questo modo:

public static void main(String[] args) {
  for(int i=0;i<10;i++){
    new ClassicIntTest().start();
  }
 }

Lanciando il main può accadere di avere il seguente output:

CLASSICO: Incremento e recupero il valore 1
CLASSICO: Incremento e recupero il valore 2
CLASSICO: Incremento e recupero il valore 3
CLASSICO: Incremento e recupero il valore 4
CLASSICO: Incremento e recupero il valore 5
CLASSICO: Incremento e recupero il valore 6
CLASSICO: Incremento e recupero il valore 7
CLASSICO: Incremento e recupero il valore 8
CLASSICO: Incremento e recupero il valore 8
CLASSICO: Incremento e recupero il valore 9


Come possiamo vedere il risultato non è quello che ci attenderemmo, in quanto non essendoci sincronizzazione sulla variabile intera (che è statica) capita che 2 thread leggano lo stesso valore in quanto accedono nel medesimo istante al metodo.

Se utilizziamo invece l'AtomicInteger questo non accade.
Esempio:

package it.threads;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntTest extends Thread {
 private static AtomicInteger intero=new AtomicInteger(0);
 public void run(){
  System.out.println("ATOMIC: Incrementa e recupera il valore "+intero.incrementAndGet());
 }
}


Se nel main precedente sostituiamo la classe ClassicIntTest con la AtomicIntTest avremo invece sempre l'output atteso, ossia:

ATOMIC: Incrementa e recupera il valore 1
ATOMIC: Incrementa e recupera il valore 2
ATOMIC: Incrementa e recupera il valore 3
ATOMIC: Incrementa e recupera il valore 4
ATOMIC: Incrementa e recupera il valore 5
ATOMIC: Incrementa e recupera il valore 6
ATOMIC: Incrementa e recupera il valore 8
ATOMIC: Incrementa e recupera il valore 7
ATOMIC: Incrementa e recupera il valore 9
ATOMIC: Incrementa e recupera il valore 10

domenica 8 dicembre 2013

Esempio zip file con Java 7

Di seguito un esempio su come zippare un file in Java utilizzando le features della Java7 in particolare:
  1. Il try with resources, che ci risparmia la fatica di dover chiudere gli stream aperti, basta dichiarare tutte le aperture nel blocco di parentesi tonde del try;
  2. Le suppressed exceptions, ossia la possibilità di farsi stampare nel catch anche tutte le altre eccezioni eventualmente riscontrate nel blocco delle parentesi tonde del try. 
Esempio


package it.varie;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipFile {
public static final int CHUNK=1024;
public static final String DIR="C:\\lav\\workspace\\wsTest\\Java7Cert\\src\\";
public static void main(String[] args) {
  if(args.length==0){
   System.err.println("Attenzione passare come parametro il nome file");
   System.exit(-1);
  }
  String fileName=args[0];
  String zipFileName=fileName+".zip";
  byte[] buffer=new byte[CHUNK];
  try( ZipOutputStream zipFile=new ZipOutputStream(new FileOutputStream(zipFileName));
    FileInputStream fis=new FileInputStream(DIR+fileName);
    )
    {
            zipFile.putNextEntry(new ZipEntry(zipFileName));
            int lenRead=0;
            while((lenRead=fis.read(buffer))>0){
             zipFile.write(buffer, 0, lenRead);
            }
    }
  catch(Exception e){
   System.out.println("Eccezione: "+e);
   System.out.println("Eventuali eccezioni soppresse");
   for(Throwable t: e.getSuppressed()){
    System.out.println(t);
   }
  }
 }
}


sabato 16 novembre 2013

Java7 watch service

Una feature molto utile è quella del WatchService, che consente di registrare una directory e notificare ogni evento che viene compiuto su di essa (es. inserimento nuovi file, cancellazioni file,modifiche eccetera).
Si ottiene questo risultato seguendo la seguente serie di passaggi logici:
  1. Ottenere un'istanza del WatchService dalla classe FileSystem;
  2. Registrare la directory di interesse, specificando nei varargs tutti gli eventi per cui si vuole registrarla;
  3. Effettuare un loop infinito dove si attendono gli eventi. Si utilizza il metodo take() per ottenere l'evento appena disponibile. La chiamata a take() è bloccante, se si vuole invece la versione non bloccante bisogna invocare il poll();
  4. Una volta ottenuto l'evento di tipo WatchKey si cicla tra tutti gli eventi disponibili per ottenere quello di interesse;
  5. Una volta processato l'evento si resetta la chiave (key.reset() nel codice), senza questo passaggio soltanto il primo evento nella directory sarà registrato.
Vediamo il codice:

package it.test;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
public class ObserveDirChanges {

 public static void main(String[] args) {
  Path p=Paths.get("c:\\excel");
  WatchService ws=null;
  try
  {
ws=p.getFileSystem().newWatchService();
p.register(ws, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE,StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.OVERFLOW);
for(;;){
WatchKey key=null;
try
{
key=ws.take();
}
catch(InterruptedException ex){
ex.printStackTrace();
}
for(WatchEvent<?> event:key.pollEvents()){
switch(event.kind().name()){
 case "OVERFLOW":
 System.out.println("Attenzione è andato perduto un evento");
 break;
 case "ENTRY_MODIFY":
 System.out.println("File "+event.context()+" modificato");
 break;
 case "ENTRY_CREATE":
 System.out.println("File "+event.context()+" creato");
 break;
 case "ENTRY_DELETE":
 System.out.println("File "+event.context()+" cancellato");
 break;
 }
 key.reset();
    }
      }
  }
  catch(IOException e){
   e.printStackTrace();
  }

 }

}


JAVA 7 ottenere informazioni su data creazione file

Con le nuove API è possibile ottenere semplicemente molte informazioni sulla natura dei file.
Nel seguente esempio vediamo come ottenere queste informazioni utilizzando l'interfaccia java.nio.file.attribute.BasicFileAttributes.


package it.test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
public class CheckAttributiFile {
 public static void main(String[] args) {
  Path p=Paths.get("c:\\excel\\2_BAHIA.xls");
  try
  {
BasicFileAttributes fileAttributes=Files.readAttributes(p, BasicFileAttributes.class);
System.out.println("Size: "+fileAttributes.size());
System.out.println("Directory: "+fileAttributes.isDirectory());
System.out.println("File normale: "+fileAttributes.isRegularFile());;
System.out.println("Link simbolico: "+fileAttributes.isSymbolicLink());
System.out.println("Ultima modifica: "+fileAttributes.lastModifiedTime());
System.out.println("Ultimo accesso:"+fileAttributes.lastAccessTime());
System.out.println("Data creazione file: "+fileAttributes.creationTime());
  }
  catch (IOException e) {
   e.printStackTrace();
  }
 }
}


 Il risultato è il seguente:

Size: 5120
Directory: false
File normale: true
Link simbolico: false
Ultima modifica: 2013-08-08T09:04:30.744618Z
Ultimo accesso:2013-04-04T06:56:47.668827Z
Data creazione file: 2013-04-04T06:56:47.668827Z

Java 7 classe java.nio.file.Files esempio creazione link simbolico

Con  la classe Files si può fare praticamente di tutto a livello di file system con semplici ed intuitivi metodi.
Vediamo come creare e testare la creazione di un link simbolico:

package it.test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FilesExample {
 public static void main(String[] args) throws IOException{
  Path p3=Paths.get("C:\\lav\\testFile\\simbolicLink.txt");
  Path p4=Paths.get("C:\\lav\\testFile\\fileReale.txt");
  System.out.println(Files.createFile(p4));
  Files.createSymbolicLink(p3, p4);
  System.out.println(Files.isSymbolicLink(p3));
  
 }
 
}


Andando sulla directory del filesystem via dos vedremo quindi:

JAVA NIO package interfaccia Path

Con java 7 abbiamo un package java.nio.file con interessanti feature per lo scandagliamento del file System.
Una di queste è rappresentato dall'interfaccia java.nio.Path che consente di ottenere molte informazioni con metodi semplici ed intuitivi.
Si crea una implementazione di tale interfaccia chiamando il metodo statico get sulla classe Paths.
Esempio:

package it.test;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathExample {
public static void main(String[] args) {
  Path p=Paths.get("c:\\lav\\trash\\prof");
  System.out.println(p.getFileName());
        System.out.println(p.getRoot());
        System.out.println(p.getParent());
        for(Path element:p){
         System.out.println(element.toString());
        }
 }

}



Ci fornisce l'output seguente:

prof
c:\
c:\lav\trash
lav
trash
prof

In questo altro esempio ho preso il path relativo al progetto Java di test, utilizzando anche ulteriori metodi dell'interfaccia come il toAbsolutePath() o il toUri().

package it.test;
import java.io.IOException;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathExample {
public static void main(String[] args) throws IOException {
  Path p=Paths.get("src");
  System.out.println("File name: "+p.getFileName());
        System.out.println("Root: "+p.getRoot());
        System.out.println("Parent: "+p.getParent());
        for(Path element:p){
         System.out.println(element.toString());
        }
        System.out.println("Absolute path: "+p.toAbsolutePath());
        System.out.println("Uri: "+p.toUri());
        System.out.println("Path normalized:"+p.normalize().toString());
        System.out.println("Real path: "+p.toRealPath(LinkOption.NOFOLLOW_LINKS));
        
 }

}


Risultato:

File name: src
Root: null
Parent: null
src
Absolute path: C:\lav\workspace\wsTest\Java7Cert\src
Uri: file:///C:/lav/workspace/wsTest/Java7Cert/src/
Path normalized:src
Real path: C:\lav\workspace\wsTest\Java7Cert\src

In particolare:
  • toUri() ritorna un path che può essere aperto da un browser ;
  • toAbsolutePath() ritorna il path assoluto dato un path relativo;
  • normalize() rimuove simboli non necessari (es. "." e "..");
  • toRealPath() ritona il path assoluto e normalizzato e può risolvere anche i symbolic link (nel caso in esame usando l'opzione NOFOLLOWLINKS è stato scelto di non considerare i link simbolici. A differenza degli altri metodi esposti però se il file non esiste fisicamente lancia una eccezione tipo IOException.
E' possibile anche effettuare delle comparazioni tra path, ed esistono 2 metodi:
  • compareTo che effettua un confronto puramente lessicografico e torna 0 se i path sono uguali;
  • equals() che effettua un confronto reale tra i path (ma bisogna accertarsi che i percorsi di entrambi i path siano percorsi assoluti).
Esempio:

 // comparing paths
        Path p2=Paths.get("C:\\lav\\workspace\\wsTest\\Java7Cert\\src");
        System.out.println(p.compareTo(p2)==0?"OK":"KO");
        System.out.println(p.equals(p2));
        System.out.println(p.toAbsolutePath().equals(p2));

In questo caso ci torna prima KO, poi false e poi true (quando si confrontano i path entrambi assoluti).

mercoledì 28 agosto 2013

Java 7 try with resources

Con Java 7 è stato introdotto il concetto di try with resources.
Essendo comune il problema di chiudere le risorse utilizzate , siano esse connessioni al db piuttosto che BufferedReader etc. etc., Java 7 introduce questa feature proprio per risolvere  queste mancanze.
Vediamo un esempio:

public static void main(String[] args) {
 String url="jdbc:mysql://localhost:3306/";
 String db="addressBook";
 String username="root";
 String password="admin";
 try(Connection connection=DriverManager.getConnection(url+db,username,password)){
     System.out.println("Connessione ok!!!");
 }
 catch(Exception ex){
     ex.printStackTrace();
 }
}

Come possiamo vedere dopo il try, ma prima dell'inizio del blocco try con le parentesi graffe, è creata la connessione.
Automaticamente sarà chiusa alla fine del programma da Java, senza necessità di farlo esplicitamente.
Si possono usare anche con più risorse, scrivendole di seguito alla prima. L'unica regola è che le varie risorse devono essere separate da ; tranne l'ultima.

Esempio:

try (FileWriter fw = new FileWriter(file);
            BufferedWriter bw = new BufferedWriter(fw)) {
        bw.write(text);
    } catch (IOException ex) {
        // handle ex
    }


Notiamo nell'esempio di recupero connessione che abbiamo utilizzato JDBC 4.0 ; con questa libreria non è più necessario  cercare il driver per la connessione al db tramite l'istruzione Class.forName utilizzata nelle precedenti versioni.
L'importante è che il driver sia nel classpath, se c'è la JVM lo trova da solo e ci risparmia un ulteriore passaggio nel codice , dove bisognava per altro indicare il nome esatto del driver utilizzato (nel caso di Mysql  com.mysql.jdbc.Driver).

lunedì 15 luglio 2013

Rilanciamento eccezioni con "type-checking" inclusivo

Questa feature introdotta con la Java 7 e ben spiegata nel sito oracle (http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html#rethrow) consente di rilanciare eccezioni specifiche senza dover utilizzare la generica Exception.
Il compilatore infatti a Runtime è in grado di capire di quale eccezione si tratta.
Vediamo un esempio:


public class Exceptions {
   static class Eccezione1 extends Exception { }
   static class Eccezione2 extends Exception { }
   public static  void rethrowException(String exceptionName) throws Eccezione1,Eccezione2 {
     try {
      switch(exceptionName){
      case "uno":
       throw new Eccezione1();
      case "due":
      throw new Eccezione2();
      default:
       System.out.println("Nessuna eccezione");
      
      }
      
     } catch (Exception e) {
       throw e;
     }
   }
}


Nelle versioni precedenti di Java saremmo stati costretti a mettere nel throws Exception, adesso invece possiamo rilanciare le nostre eccezioni specifiche.


domenica 11 settembre 2011

Java 7 esempi di utilizzo nuove feature


Per utilizzare Java 7 conviene scaricarsi NetBeans 7, che al momento garantisce una integrazione perfetta con la jdk 7.
Con Eclipse Indigo, pur avendo incluso nel classpath le librerie di Java 7 , non sono riuscito a  compilare con livello di compliance java 7; cercando su Internet ho visto che bisogna installare delle patch, quindi per adesso conviene aspettare una release nuova del software con la Java 7 integrata.

Di seguito un paio di esempi di codice “nuovo” con Java 7 (mano a mano che approfondirò posterò gli altri)

Map<String,List<String>> mappa=new HashMap<>();
List<String> lista=new ArrayList<>();
lista.add("uno");
lista.add("due");
mappa.put("test", lista);

Come possiamo vedere nella new non è più necessario specificare di nuovo i tipi.

Un'altra caratteristica interessante è questa: dato un codice che, a seconda della logica applicativa effettua la throw di eccezioni diverse, è possibile avere un unico catch per più eccezioni.
L'unico requisito è che le eccezioni, anche se sono di tipo unchecked, siano esplicitamente lanciate dal codice.

Esempio

private void testException(int v){
try
{
if(v==1) throw new IllegalArgumentException("eccezione 1");
else throw new ArithmeticException("eccezione 2");
}
catch(IllegalArgumentException | ArithmeticException ex){
ex.printStackTrace();
throw ex;
}
}

Qui a seconda del parametro inserito verrà effettuata la throw di una IllegalArgumentException oppure di una ArithmeticException. Se nel try non si effettua alcuna throw il codice però non compila.


Java 7 finalmente switch su valori Stringa

Finalmente con la versione di Java 7 è possibile utilizzare lo switch sui valori Stringa.  Era da anni che la comunità di sviluppatori chiedeva questa funzionalità, che linguaggi come C# hanno fin dalle primissime versioni (io lo usai nel 2003 e già c'era...).
Fino alla Java 6 era infatti possibile effettuare switch solo su tipi numerici oppure enum, il che portava, quando si trattava di Stringhe, a scrivere un sacco di if else if.
Di seguito vediamo un semplice esempio di utilizzo della nuova feature.


package it.test;

public class Hello {
public static void main(String[] args){
String utente=args[0];
System.out.println(salutaUtente(utente));
}
static String salutaUtente(String s) {
String retVal="Ciao ";
switch(s) {
case "user":
retVal+="utente base";
break;
case "admin":
retVal+="utente avanzato";
break;
default: retVal+=s+" non sei un utente";
break;
}
return retVal;
}
}