// Loosely based on Arnold, Gosling, Holmes p. 252

class PhilosopherThread implements Runnable {
    /*@non_null@*/ private Philosopher philosopher;

    public PhilosopherThread (/*@non_null@*/ Philosopher p) {
	philosopher = p;
    }

    public void run () {
	philosopher.philosophize ();
    }
}

public class Philosopher {
    private Philosopher colleague;
    private String name;
    private String quote;

    public Philosopher (String name, String quote) {
	this.name = name;
	this.quote = quote;
    }

    public synchronized void setColleague (Philosopher p) {
	colleague = p;
    }

    public synchronized void philosophize () {
	System.err.println (name + "[Thread " + Thread.currentThread().getName () + "] says " + quote);

	if (colleague != null) { // Need a colleague to start and argument.
	    colleague.argue ();
	} 
    }

    public synchronized void argue () {
	System.err.println (name + "[Thread " + Thread.currentThread().getName () + "] argues: No! " + quote);
    }

    public static void main (String [] args) {
	Philosopher descartes = new Philosopher ("Descartes", "I think, therefore I am.");
	Philosopher plato = new Philosopher ("Plato", "The life which is unexamined is not worth living.");
	
	descartes.setColleague (plato);
	plato.setColleague (descartes);

	Thread dthread = new Thread (new PhilosopherThread (descartes));
	Thread pthread = new Thread (new PhilosopherThread (plato));

	dthread.start ();
	pthread.start ();
    }
}