Runnable 接口非常简单,只定义了一个无参无返回值的 run 方法,源码如下。
@FunctionalInterfacepublic interface Runnable { public abstract void run();}
下面我们分析一下 Thread 中的 run 方法。
@Overridepublic void run() { // 如果构造 Thread 时传递了 Runable,则会执行 Runnable 中的 run 方法 if (target != null) { target.run(); } // 否则需要重写 Thread 类的 run 方法}
准确的讲,创建线程只有一种方式,那就是构造 Thread 类,而实现线程的执行单元则有两种方式,第一种是重写 Thread 的 run 方法,第二种是实现 Runnable 接口的 run 方法,并且将 Runnable 实例用作构造 Thread 的参数。
二 Runnable 版的叫号程序package concurrent;public class TicketWindowRunnable implements Runnable { // 不用 static 进行修饰 private int index = 1; private final static int MAX = 50; @Override public void run() { while (index <= MAX) { System.out.println(Thread.currentThread() + "的号码是:" + (index++)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final TicketWindowRunnable task = new TicketWindowRunnable(); Thread windowThread1 = new Thread(task, "1号窗口"); Thread windowThread2 = new Thread(task, "2号窗口"); Thread windowThread3 = new Thread(task, "3号窗口"); Thread windowThread4 = new Thread(task, "4号窗口"); windowThread1.start(); windowThread2.start(); windowThread3.start(); windowThread4.start(); }}
三 测试四 分析Thread[1号窗口,5,main]的号码是:1
Thread[3号窗口,5,main]的号码是:2
Thread[2号窗口,5,main]的号码是:1
Thread[4号窗口,5,main]的号码是:3
Thread[2号窗口,5,main]的号码是:4
Thread[3号窗口,5,main]的号码是:5
Thread[4号窗口,5,main]的号码是:4
Thread[1号窗口,5,main]的号码是:4
Thread[1号窗口,5,main]的号码是:6
Thread[4号窗口,5,main]的号码是:9
Thread[3号窗口,5,main]的号码是:8
Thread[2号窗口,5,main]的号码是:7
Thread[3号窗口,5,main]的号码是:11
Thread[4号窗口,5,main]的号码是:10
Thread[2号窗口,5,main]的号码是:13
Thread[1号窗口,5,main]的号码是:12
Thread[4号窗口,5,main]的号码是:14
Thread[3号窗口,5,main]的号码是:17
Thread[1号窗口,5,main]的号码是:16
Thread[2号窗口,5,main]的号码是:15
Thread[2号窗口,5,main]的号码是:18
Thread[4号窗口,5,main]的号码是:19
Thread[1号窗口,5,main]的号码是:21
Thread[3号窗口,5,main]的号码是:20
Thread[1号窗口,5,main]的号码是:22
Thread[3号窗口,5,main]的号码是:23
Thread[2号窗口,5,main]的号码是:24
Thread[4号窗口,5,main]的号码是:22
Thread[3号窗口,5,main]的号码是:26
Thread[1号窗口,5,main]的号码是:27
Thread[4号窗口,5,main]的号码是:25
Thread[2号窗口,5,main]的号码是:25
Thread[3号窗口,5,main]的号码是:28
Thread[1号窗口,5,main]的号码是:29
Thread[2号窗口,5,main]的号码是:28
Thread[4号窗口,5,main]的号码是:28
Thread[3号窗口,5,main]的号码是:31
Thread[4号窗口,5,main]的号码是:30
Thread[1号窗口,5,main]的号码是:33
Thread[2号窗口,5,main]的号码是:32
Thread[4号窗口,5,main]的号码是:34
Thread[1号窗口,5,main]的号码是:35
Thread[3号窗口,5,main]的号码是:34
Thread[2号窗口,5,main]的号码是:36
Thread[4号窗口,5,main]的号码是:37
Thread[3号窗口,5,main]的号码是:37
Thread[2号窗口,5,main]的号码是:39
Thread[1号窗口,5,main]的号码是:38
Thread[2号窗口,5,main]的号码是:40
Thread[3号窗口,5,main]的号码是:41
Thread[4号窗口,5,main]的号码是:42
Thread[1号窗口,5,main]的号码是:43
Thread[1号窗口,5,main]的号码是:44
Thread[4号窗口,5,main]的号码是:45
Thread[3号窗口,5,main]的号码是:44
Thread[2号窗口,5,main]的号码是:44
Thread[3号窗口,5,main]的号码是:46
Thread[1号窗口,5,main]的号码是:49
Thread[2号窗口,5,main]的号码是:48
Thread[4号窗口,5,main]的号码是:47
Thread[2号窗口,5,main]的号码是:50
Thread[1号窗口,5,main]的号码是:53
Thread[4号窗口,5,main]的号码是:51
Thread[3号窗口,5,main]的号码是:52
Process finished with exit code 0
Runnable 版本的叫号程序,使用了同一个 Runnable 接口,四个线程的资源是共享的,针对 index,不再需要用 static 进行修饰,这是一个改进,但共享资源 index 存在线程安全问题,这一点在以后再进一步优化。