août
2010
Java Quiz #41 : time attack !
(FR)
La cellule d'expertise de votre entreprise a développé un Timer pour que vous puissiez mesurer les performances de votre application, mais... ils ont juste oublié de fournir une méthode pour récupérer la valeur du compteur ! Comment faire pour l'afficher une fois la mesure prise ?
Vous ne pouvez intervenir que sur la classe Quiz41, et il est interdit de modifier le code existant ou d'utiliser la Réflexion.
Bonne chance !
(EN)
The Architects Team developed a Timer class to help you measure the performance of your code, but... they forgot to provide a method to get the timer's value ! How can you get it back and print it in the console ?
You can only alter the Quiz41 class ; modifying the already existing code or using Reflection is forbidden.
Good luck !
public class Quiz41 { public static void main(String[] args) throws InterruptedException { Timer timer = new Timer(); timer.start(); Thread.sleep(new Random().nextInt(2000)); timer.stop(); } }
public class Timer { private TimerThread thread = new TimerThread(); public void start() { thread.start(); } public void stop() { thread.stop(); } public static class TimerThread extends Thread { private AtomicInteger counter = new AtomicInteger(0); @Override public void run() { try { while (!isInterrupted()) { counter.incrementAndGet(); Thread.sleep(100); } } catch (InterruptedException e) { interrupt(); } } public int getCounter() { return counter.get(); } } }
Réponse / Answer :
Soon !


Commentaires
Solution rapide :
On récupère les threads (y compris les threads 'fils') dans un tableau.
Le deuxième élément est le TimerThread que l'on cast et on récupère le counter !
Et voilà !
timer.stop();
Thread threads = new Thread[2];
Thread.enumerate(threads);
Thread thread = threads[1];
System.out.println(((Timer.TimerThread) thread).getCounter());
Je propose (on est bien d'accord que je n'écrirai jamais du code comme ça en production :-) ) :
public static void main(String args) throws InterruptedException {
Timer timer = new Timer();
timer.start();
// My code : begin
Set<Thread> allThreads = Thread.getAllStackTraces().keySet();
TimerThread timerThread = null;
for (Thread thread : allThreads) {
if (thread instanceof TimerThread) {
timerThread = (TimerThread)thread;
break;
}
}
// My Code : end
Thread.sleep(new Random().nextInt(2000));
timer.stop();
if ( timerThread == null ) {
System.exit(0);
}
System.out.println("counter = " + timerThread.getCounter());
}
public class Quiz41 {
public static void main(String[] args) throws InterruptedException { EH eh = new EH(); Thread.setDefaultUncaughtExceptionHandler(eh); Timer timer = new Timer(); timer.start(); Thread.sleep(new Random().nextInt(2000)); timer.stop(); Thread.sleep(1000); System.out.println(eh.getCounter()); } static class EH implements UncaughtExceptionHandler { volatile int counter; @Override public void uncaughtException(Thread t, Throwable e) { TimerThread tt = (TimerThread) t; counter = tt.getCounter(); } public int getCounter() { return counter; } }}
public static void main(String args) throws InterruptedException {
executeInNewGroup(new Runnable() { @Override public void run() { try { Timer timer = new Timer(); timer.start(); Thread[] tmpThreads = new Thread[2]; Thread.currentThread().getThreadGroup().enumerate(tmpThreads); Timer.TimerThread timerThread = (Timer.TimerThread) tmpThreads[1]; Thread.sleep(new Random().nextInt(2000)); timer.stop(); System.out.println(timerThread.getCounter()); } catch (Exception ex) { ex.printStackTrace(); } } }); }public static void executeInNewGroup(Runnable runnable) throws InterruptedException { final ThreadGroup group = new ThreadGroup("mygroup"); Thread thread = new Thread(group, runnable); thread.start(); thread.join(); }Comme d'habitude, j'ai du mal à trouver la solution, mais les commentaires sont tous plus intéressants les uns que les autres :-) Quelle ingéniosité et quelle connaissance des API !
Merci Olivier pour ces énigmes :-)
Since the nested class is both public and static
public class Quiz41 {
public static void main(String args) throws InterruptedException {
TimerThread timer = new TimerThread();
timer.start();
Thread.sleep(new Random().nextInt(2000));
timer.stop();
System.out.println(timer.getCount())
}
}
Par classe anonyme, je modifie le comportement de la méthode stop() en utilisant un autre objet TimerThread, n'ayant pas accès à l'original déclaré private, non visible dans l'héritage :
Timer timer = new Timer() {
private TimerThread thread2 = new TimerThread();
@Override
public void start() { thread2.start(); }
@Override
public void stop() { thread2.stop(); System.out.println("Counter: " + thread2.getCounter()); }
};
timer.start();
Thread.sleep(new Random().nextInt(2000));
timer.stop();