001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.core.issue;
015
016import java.util.concurrent.locks.Lock;
017import java.util.concurrent.locks.ReentrantLock;
018
019/**
020 * Example code illustrating locking policies in the JDK.
021 * See http://jira.qos.ch/browse/LBCORE-97 for a discussion.
022 * 
023 * @author Joern Huxhorn
024 */
025public class LBCORE97 {
026
027    static int THREAD_COUNT = 10;
028
029    public static void main(String args[]) throws InterruptedException {
030
031        System.out.println("Environment:");
032        System.out.println("java.runtime.name    = " + System.getProperty("java.runtime.name"));
033        System.out.println("java.runtime.version = " + System.getProperty("java.runtime.version"));
034        System.out.println("java.vendor          = " + System.getProperty("java.vendor"));
035        System.out.println("java.version         = " + System.getProperty("java.version"));
036        System.out.println("java.vm.name         = " + System.getProperty("java.vm.name"));
037        System.out.println("java.vm.info         = " + System.getProperty("java.vm.info"));
038
039        System.out.println("os.name              = " + System.getProperty("os.name"));
040        System.out.println("os.version           = " + System.getProperty("os.version"));
041        System.out.println("os.arch              = " + System.getProperty("os.arch"));
042        System.out.println("##########################################");
043
044        usingSynchronized(THREAD_COUNT);
045        usingUnfairLock(THREAD_COUNT);
046        usingFairLock(THREAD_COUNT);
047    }
048
049    public static void execute(String text, Thread[] threads) throws InterruptedException {
050        System.out.println("About to execute " + text + "...");
051        int threadCount = threads.length;
052        for (int i = 0; i < threadCount; i++) {
053            threads[i].start();
054        }
055
056        Thread.sleep(10000);
057
058        for (int i = 0; i < threadCount; i++) {
059            threads[i].interrupt();
060        }
061        Thread.sleep(1000); // wait a moment for termination, to lazy for join ;)
062    }
063
064    public static void print(String text, Runnable[] runnables) {
065        System.out.println("Results for " + text + ":");
066        for (int i = 0; i < runnables.length; i++) {
067            System.out.println("runnables[" + i + "]: " + runnables[i]);
068        }
069        System.out.println("##########################################");
070    }
071
072    public static void usingSynchronized(int threadCount) throws InterruptedException {
073        Object lockObject = new Object();
074        Runnable[] runnables = new Runnable[threadCount];
075        Thread[] threads = new Thread[threadCount];
076
077        for (int i = 0; i < threadCount; i++) {
078            runnables[i] = new SynchronizedRunnable(lockObject);
079            threads[i] = new Thread(runnables[i]);
080        }
081        String text = "usingSynchronized";
082        execute(text, threads);
083        print(text, runnables);
084    }
085
086    public static void usingUnfairLock(int threadCount) throws InterruptedException {
087        Lock lock = new ReentrantLock();
088        Runnable[] runnables = new Runnable[threadCount];
089        Thread[] threads = new Thread[threadCount];
090
091        for (int i = 0; i < threadCount; i++) {
092            runnables[i] = new LockRunnable(lock);
093            threads[i] = new Thread(runnables[i]);
094        }
095
096        String text = "usingUnfairLock";
097        execute(text, threads);
098        print(text, runnables);
099    }
100
101    public static void usingFairLock(int threadCount) throws InterruptedException {
102        Lock lock = new ReentrantLock(true);
103        Runnable[] runnables = new Runnable[threadCount];
104        Thread[] threads = new Thread[threadCount];
105
106        for (int i = 0; i < threadCount; i++) {
107            runnables[i] = new LockRunnable(lock);
108            threads[i] = new Thread(runnables[i]);
109        }
110
111        String text = "usingFairLock";
112        execute(text, threads);
113        print(text, runnables);
114    }
115
116    public static class SynchronizedRunnable implements Runnable {
117        private final Object lockObject;
118        private int counter;
119        private boolean running;
120
121        public SynchronizedRunnable(Object lockObject) {
122            this.lockObject = lockObject;
123            this.counter = 0;
124            this.running = false;
125        }
126
127        public void run() {
128            running = true;
129            for (;;) {
130                synchronized (lockObject) {
131                    counter++;
132                    try {
133                        Thread.sleep(10);
134                    } catch (InterruptedException ex) {
135                        break;
136                    }
137                }
138            }
139            running = false;
140        }
141
142        public String toString() {
143            return "SynchronizedRunnable[counter=" + counter + ", running=" + running + "]";
144        }
145    }
146
147    public static class LockRunnable implements Runnable {
148        private final Lock lock;
149        private int counter;
150        private boolean running;
151
152        public LockRunnable(Lock lock) {
153            this.lock = lock;
154            this.counter = 0;
155            this.running = false;
156        }
157
158        public void run() {
159            running = true;
160            for (;;) {
161                lock.lock();
162                try {
163                    counter++;
164                    Thread.sleep(10);
165                } catch (InterruptedException ex) {
166                    break;
167                } finally {
168                    lock.unlock();
169                }
170            }
171            running = false;
172        }
173
174        public String toString() {
175            return "LockRunnable[counter=" + counter + ", running=" + running + "]";
176        }
177    }
178}