用好多线程重要的是协调线程调用资源,下面看一个实例:
三个线程,第一个线程循环输出三条信息,第二个线程循环输出两条信息,第三个线程循环输出一条信息,按照一二三线程顺序依次输出,然后按照这个顺序循环五回。
多线程依次输出,依次控制就是多线程需要访问的共享资源。
public class ThreadTest { public static class ChildRun implements Runnable { private ThreadTest thread; public ChildRun(ThreadTest thread) { this.thread = thread; } @Override public void run() { for (int i = 0; i < 5; i ++) { thread.showChild(); } } } public static class GrandsonRun implements Runnable { private ThreadTest thread; public GrandsonRun(ThreadTest thread) { this.thread = thread; } @Override public void run() { for (int i = 0; i < 5; i ++) { thread.showGrandson(); } } } private int status = 0; public synchronized void showParent() { if (0 != this.status) { try { this.wait(); if (0 != this.status) { this.showParent(); return ; } } catch (InterruptedException e) { e.printStackTrace(); } } for (int i = 0; i < 3; i ++) { System.out.println("parent"); } this.notifyAll(); this.status = 1; } public synchronized void showChild() { if (1 != this.status) { try { this.wait(); if (1 != this.status) { this.showChild(); return ; } } catch (InterruptedException e) { e.printStackTrace(); } } for (int i = 0; i < 2; i ++) { System.out.println("child"); } this.notifyAll(); this.status = 2; } public synchronized void showGrandson() { if (2 != this.status) { try { this.wait(); if (2 != this.status) { this.showGrandson(); return ; } } catch (InterruptedException e) { e.printStackTrace(); } } for (int i = 0; i < 1; i ++) { System.out.println("grandson"); } this.notifyAll(); this.status = 0; } public static void main(String[] args) { ThreadTest thread = new ThreadTest(); ExecutorService service = Executors.newCachedThreadPool(); service.execute(new ChildRun(thread)); service.execute(new GrandsonRun(thread)); service.shutdown(); for (int i = 0; i < 5; i ++) { thread.showParent(); } } }
这里的ThreadTest类包含两个Runnbale,就是其中两个线程,而这个类本身就是一个资源共享类,里面的status就是控制顺序的状态。主线程内首先创建执行了第二三个线程,使这两个线程先进入等待状态,然后再执行主线程的,待主线程完毕之后唤醒其他两条线程,这时候可能会进入不该进入的线程三,所以在wait后面又进行了一次判断,使它能继续保持等待状态让出执行权,直到状态符合的情况下进行执行。
注意几个问题:
1、一定要让等待的线程先执行,不然会出现主线程通知时,没有找到等待的线程而产生的阻塞。
2、wait之后的再次判断很重要,因为在超过两个线程的情况下,不确定是不是通知的该线程。