3

J'utilise c3p0 pour gérer le regroupement de connexions de base de données dans un environnement multithread. La question peut concerner d'autres bibliothèques de mise en commun, mais c'est ce que j'ai.Mise en pool de connexions et Thread.interrupt()

Récemment, j'ai besoin pour mettre en œuvre interrupt manipulation d'ions sur ces fils en utilisant c3p0 directement ou indirectement, et ont remarqué que si interrupt() est appelé à droite quand c3p0Datasource.getConnection() tente de me chercher un Connection de la piscine, il jette un InterruptedException.

De toute évidence, cela se produit à cause de la wait()

at java.lang.Object.wait(Native Method) 
at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1414) 

cool. La question est de savoir comment gérer cela correctement - à la fois le cas a) vous voulez continuer avec la transaction avant que votre thread se termine, et b) vous voulez abandonner.

J'ai essayé une solution qui semble fonctionner correctement (affichée comme réponse) - en fait, je pense que ce sujet est fermé. Ne hésitez pas à puce dans le cas contraire, merci!

Répondre

3

J'ai fait un test simple en tirant un grand nombre de demandes Connection en 1 seconde, l'exécution d'un SELECT chaque fois tim assurez-vous que les goulots d'étranglement de la piscine, puis appeler interrupt().

Ce que je trouve que l'objet était connection est bien et dandy après la InterruptedException d'être pris, même si le stacktrace me montre l'effondrement c3p0 à awaitAvailable(..). A ce moment même je vérifie leurs sources, et sûrement, ils traitent le InterruptedException. Ils ont même jeter un avertissement approprié:

WARNING: [email protected] -- an attempt to checkout a resource was interrupted, and the pool is still live: some other thread must have either interrupted the Thread attempting checkout! 

nous dire qu'il est toujours vivant, mais inbetween beaucoup de mot fuzz. Résolu.

Voici le test de toute façon.

ComboPooledDataSource ds = new ComboPooledDataSource(); 

// testing with various pool sizes - same effect 
ds.setMinPoolSize(1); 
ds.setMaxPoolSize(5); 
ds.setInitialPoolSize(2); 

Thread connectingThread = new Thread() { 

    public void run() { 
     Connection cnxn = null; 
     while (true) { 
      try { 
       cnxn = ds.getConnection(); 
       System.out.println("Got connection.); 
       executeQuery(cnxn); 
      } catch (SQLException e) { 
       System.out.println("Got exception."); 
       e.printStackTrace(); 

       // SOLUTION: 
       Throwable cause = e.getCause(); 
       if (cause instanceof InterruptedException) { 
        System.out.println("Caught InterruptedException! Cnxn is " + cnxn); 

        // note that cnxn is a com.mchange.v2.c3p0.impl.NewProxyConnection 
        // also note that it's perfectly healthy. 
        // 
        // You may either want to: 
        // a) use the cnxn to submit your the query 

        executeQuery(cnxn); 
        cnxn.close() 

        // b) handle a proper shutdown 

        cnxn.close(); 

       } 
       break; 
      } 
     } 
    }; 
}; 

connectingThread.start(); 

try { 
    Thread.sleep(1000); 
} catch (InterruptedException e) {   e.printStackTrace();  } 

connectingThread.interrupt(); 
Questions connexes