class FooRunnable implements Runnable { int num; //for deadlock example: Object o1 = new Object(); Object o2 = new Object(); FooRunnable (int num) { this.num = num; } public void run() { //this is the task to do. can be done by several threads System.out.println("before sleep "+num+" "+this+" "+ Thread.currentThread().getName()); /* //thread runtime errors but has no effect on other threads: if (Thread.currentThread().getName().equals("Thread-2")) { System.out.println("I'm Thread-2. I'm going to crash"); //throw new Exception("puke"); //has to be reported throws by method TestThreads.ta[0].start(); //runtime error to restart a thread } */ /* try { Thread.sleep(200); } catch (InterruptedException e) {} System.out.println("after sleep "+num+this+" "+ Thread.currentThread().getName()); */ /* //have one thread join on another: if (Thread.currentThread().getName().equals("Thread-1")) { System.out.println("I'm Thread-1"); try {TestThreads.ta[15].join();} //wait until Thread-16 ends} catch (InterruptedException e) {} System.out.println("I'm Thread-1 after 16 ends"); } */ /* if (num == 2) { System.out.println(Thread.currentThread().getName()+ " before synchmethod call"); synchedmethod(); System.out.println(Thread.currentThread().getName()+ " after synchmethod call"); } */ /* // deadlock //if the two Objects are local here, no deadlock?? duh the objects //are separate in each thread. if (Thread.currentThread().getName().equals("Thread-1")) { //get lock on o1, sleep so thread2 can get lock on o2 synchronized (o1) { System.out.println(Thread.currentThread().getName()+ " in outer synch block"); try { Thread.sleep(3000); } catch (InterruptedException e) {} System.out.println(Thread.currentThread().getName()+ " before inner synch block"); synchronized (o2) { System.out.println(Thread.currentThread().getName()+ " in inner synch block"); } System.out.println(Thread.currentThread().getName()+ " after inner synch block"); } } if (Thread.currentThread().getName().equals("Thread-2")) { synchronized (o2) { System.out.println(Thread.currentThread().getName()+ " in outer synch block"); try { Thread.sleep(3000); } catch (InterruptedException e) {System.out.println("caught");} System.out.println(Thread.currentThread().getName()+ " before inner synch block"); synchronized (o1) { System.out.println(Thread.currentThread().getName()+ " in inner synch block"); } System.out.println(Thread.currentThread().getName()+ " after inner synch block"); } } */ /* //wait-notify example: if (Thread.currentThread().getName().equals("Thread-1")) { //synch on Thread-2 (before it does notify System.out.println(Thread.currentThread().getName()+ "before synch block"); synchronized(TestThreads.ta[1]) { System.out.println(Thread.currentThread().getName()+ " in synch block before wait call"); try { TestThreads.ta[1].wait(); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName()+ " caught InterruptedException"); } System.out.println(Thread.currentThread().getName()+ " after wait call"); } System.out.println(Thread.currentThread().getName()+ "after synch block"); } if (Thread.currentThread().getName().equals("Thread-2")) { //synch on self System.out.println(Thread.currentThread().getName()+ "before synch block"); synchronized(this) { System.out.println(Thread.currentThread().getName()+ " in synch block before notify call"); notify(); System.out.println(Thread.currentThread().getName()+ " after notify call"); } System.out.println(Thread.currentThread().getName()+ "after synch block"); } */ } //method of FooRunnable, not Thread public void othermethod() { System.out.println(Thread.currentThread().getName()+" othermethod"); } public synchronized void synchedmethod() { System.out.println(Thread.currentThread().getName()+ " in synchmethod call"); try { Thread.sleep(3000); } catch (InterruptedException e) {} } } public class TestThreads { final static int maxthreads=16; static Thread[] ta = new Thread[maxthreads]; //instead of local to main. so that can be accessed by Foo objects public static void main (String [] args) { FooRunnable[] ra = new FooRunnable[4]; //FooRunnable r = new FooRunnable(); for (int i=0; i<4; i++) { ra[i] = new FooRunnable(i); //runnable object for (int j=0; j<4; j++) { //use this to have references to the threads: ta[i*4+j] = new Thread(ra[i]); //4 threads //use this to just instantiate threads and start them: //new Thread(ra[i]).start(); /* if (i*4+j == 0) System.out.println("thread 0 isAlive() or not before start: "+ ta[0].isAlive()); */ //comment out if not having references to the threads ta[i*4+j].start(); /* if (i*4+j == 0) System.out.println("thread 0 isAlive() or not before start: "+ ta[0].isAlive()); */ } } //ta[0].start(); //runtime error, re-starting dead thread System.out.println("main "+Thread.currentThread().getName()); /* try { //ta[2].join(); //wait until thread-3 ends its run for (int i=0; i