001/*
002 * Copyright (c) 2004-2013 Tada AB and other contributors, as listed below.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the The BSD 3-Clause License
006 * which accompanies this distribution, and is available at
007 * http://opensource.org/licenses/BSD-3-Clause
008 *
009 * Contributors:
010 *   Tada AB
011 */
012package org.postgresql.pljava.example;
013
014import java.util.logging.Level;
015import java.util.logging.Logger;
016
017/**
018 * This class contains thread related methods.
019 * 
020 * @author Thomas Hallgren
021 */
022public class Threads {
023    static class Locker extends Thread {
024        private final String m_name;
025        private final String m_first;
026        private final String m_second;
027
028        Locker(String name, String first, String second) {
029            m_name = name;
030            m_first = first;
031            m_second = second;
032        }
033
034        @Override
035        public void run() {
036            Logger log = Logger.getAnonymousLogger();
037            try {
038                log.info("Thread " + m_name + " wants " + m_first);
039                synchronized (m_first) {
040                    log.info("Thread " + m_name + " got " + m_first);
041                    Thread.sleep(100);
042                    log.info("Thread " + m_name + " wants " + m_second);
043                    synchronized (m_second) {
044                        log.info("Thread " + m_name + " got " + m_second);
045                    }
046                }
047            } catch (Exception e) {
048                log.log(Level.INFO, "Thread " + m_name + " got exception: ", e);
049            }
050        }
051    }
052
053    private final static String s_lockOne = "lock number one";
054
055    private final static String s_lockTwo = "lock number two";
056
057    public static void forceDeadlock() {
058        // Cause a deadlock.
059        //
060        Locker x = new Locker("x", s_lockOne, s_lockTwo);
061        Locker y = new Locker("y", s_lockTwo, s_lockOne);
062        x.start();
063        y.start();
064
065        // Sleep for a while. The logger will fail if trying to access the
066        // backend when it is not in a Java call.
067        //
068        try {
069            Logger.getAnonymousLogger().log(Level.INFO,
070                    "Main thread sleeps a while");
071            Thread.sleep(1000);
072        } catch (Exception e) {
073            Logger.getAnonymousLogger().log(Level.INFO,
074                    "Main thread interrupted while sleeping: ", e);
075        }
076    }
077}