fork download
  1. import java.util.logging.*;
  2.  
  3. public class Main {
  4. public static final LicenseManager licenseManager = new LicenseManager();
  5.  
  6. static class LicenseManager {
  7. private static final Logger logger =
  8. Logger.getLogger(LicenseManager.class.getName());
  9.  
  10. class InsufficientApplesException extends RuntimeException {};
  11. class InsufficientPiesException extends RuntimeException {};
  12.  
  13. private int apples = 10;
  14. private int pies = 10;
  15. private boolean enterpriseLoggingEnabled = true;
  16.  
  17. // Apples have high contention; so they get their own lock.
  18. private final Object appleLock = new Object();
  19.  
  20. void useApple() {
  21. checkExpired();
  22. synchronized (appleLock) {
  23. logger.info("Using apple. Apples left: " + apples + ". " + Thread.currentThread());
  24. if (apples == 0) throw new InsufficientApplesException();
  25. apples--;
  26. }
  27. }
  28.  
  29. /* Examples. There are lots of other operations like this
  30.   * on LicenseManager. We don't have time to prove that
  31.   * they are commutative, so we just use the main object lock
  32.   * around them all. The exception is when we find one with high
  33.   * contention, for example apples. */
  34. synchronized void usePear() {checkExpired(); /*...*/}
  35. synchronized void checkExpired() {}
  36.  
  37. synchronized void usePie() {
  38. checkExpired();
  39. logger.info("Using pie. Pies left: " + pies + ". " + Thread.currentThread());
  40. if (pies == 0) throw new InsufficientPiesException();
  41. boolean reallyCanUsePie = true; // do expensive pie computation
  42. if (reallyCanUsePie) {
  43. useApple(); /* using a pie requires an apple.
  44.   * TODO: stop putting apples in the pumpkin pie */
  45. pies--;
  46. }
  47. }
  48.  
  49. synchronized boolean isEnterpriseLoggingEnabled() {
  50. return enterpriseLoggingEnabled;
  51. }
  52. }
  53.  
  54. public static void main(String[] args) {
  55. // Install enterprise log handler on the root logger
  56. Logger.getLogger("").addHandler(new Handler() {
  57. @Override
  58. public void publish(LogRecord lr) {
  59. System.out.println("TEST." + lr.getMessage() + ". " + Thread.currentThread());
  60. if (licenseManager.isEnterpriseLoggingEnabled())
  61. System.out.println("ENTERPRISE ALERT! ["
  62. + lr.getLevel() + "] " + lr.getMessage() + ". " + Thread.currentThread());
  63. }
  64. @Override public void flush() {}
  65. @Override public void close() throws SecurityException {}
  66. });
  67.  
  68. // Simulate fat user
  69. new Thread() {
  70. @Override
  71. public void run() {
  72. while (true) {
  73. licenseManager.usePie();
  74. }
  75. }
  76. }.start();
  77.  
  78. // Simulate fat albeit healthy user
  79. while (true) {
  80. licenseManager.useApple();
  81. }
  82. }
  83. }
  84.  
Time limit exceeded #stdin #stdout 5s 381312KB
stdin
Standard input is empty
stdout
TEST.Using apple. Apples left: 10. Thread[main,5,main]. Thread[main,5,main]
TEST.Using pie. Pies left: 10. Thread[Thread-1,5,main]. Thread[Thread-1,5,main]
ENTERPRISE ALERT! [INFO] Using pie. Pies left: 10. Thread[Thread-1,5,main]. Thread[Thread-1,5,main]