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 {
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();