首页 > 代码库 > java:多线程基础之Runnable与Thread

java:多线程基础之Runnable与Thread

java.lang包下有二个非常有用的东西:Runnable接口与Thread类,Thread实现了Runnable接口(可以认为Thread是Runnable的子类),利用它们可以实现最基本的多线程开发。

一、Runnable入门示例

 1 public class RunnableDemo1 { 2  3     public static void main(String[] args) { 4         new Runnable() { 5             public void run() { 6                 for (int i = 0; i < 5; i++) { 7                     try { 8                         Thread.sleep(100); 9                     } catch (InterruptedException e) {10                         e.printStackTrace();11                     }12                     System.out.println("r1 -> i=" + i);13                 }14 15             }16         }.run();17 18         new Runnable() {19             public void run() {20                 for (int i = 0; i < 5; i++) {21                     try {22                         Thread.sleep(100);23                     } catch (InterruptedException e) {24                         e.printStackTrace();25                     }26                     System.out.println("r2 -> i=" + i);27                 }28             }29         }.run();30 31     }32 33 }
View Code

代码很简单,每个线程依次输出0-4这5个数字,运行结果:

r1 -> i=0
r1 -> i=1
r1 -> i=2
r1 -> i=3
r1 -> i=4
r2 -> i=0
r2 -> i=1
r2 -> i=2
r2 -> i=3
r2 -> i=4

 

二、向Runnable传递参数

实际应用中,线程开始处理前,通常会有一些初始参数,如果要传入参数,可以参考下面的方法,先定义一个Runnable的子类

 1 package com.cnblogs.yjmyzz; 2  3 public class MyRunnable implements Runnable{ 4      5     private String name; 6     private int max; 7      8     public MyRunnable(String name,int max){ 9         this.name = name;10         this.max = max;11     }12 13     public void run() {14         for (int i = 1; i <= max; i++) {15             try {16                 Thread.sleep(5);17                 System.out.println(name + ".i=" + i);18             } catch (InterruptedException e) {                    19                 e.printStackTrace();20             }                21         }            22     }23     24 }
View Code

 然后这样使用:

 1 package com.cnblogs.yjmyzz; 2  3 public class RunnableDemo2 { 4  5     public static void main(String[] args) { 6          7         new MyRunnable("A", 5).run(); 8          9         new MyRunnable("B", 5).run();10     }11 12 }
View Code

运行结果:

A.i=1
A.i=2
A.i=3
A.i=4
A.i=5
B.i=1
B.i=2
B.i=3
B.i=4
B.i=5

 

三、利用Thread并行处理

刚才的二个例子,相当大家也发现了问题,虽然是有二个线程,但是始终是按顺序执行的,上一个线程处理完成前,下一个线程无法开始,这其实跟同步处理没啥二样,可以通过Thread类改变这种局面:

 1 public class RunnableDemo3 { 2  3     public static void main(String[] args) { 4  5         Runnable r1 = new MyRunnable("A", 5); 6         Runnable r2 = new MyRunnable("B", 5); 7          8         Thread t1 = new Thread(r1); 9         Thread t2 = new Thread(r2);10         11         t1.start();12         t2.start();13         14     }15 16 }
View Code

Thread通过start方法,可以让多个线程并行处理,运行结果如下:

B.i=1
A.i=1
B.i=2
A.i=2
B.i=3
A.i=3
B.i=4
A.i=4
B.i=5
A.i=5

从输出结果上看,二个线程已经在并行处理了。

 

四、通过在线抢购示例理解资源共享

双十一刚过,每到这个时候,通常是狼多肉少,下面的OrderRunnable类模拟这种抢购情况,假设产品数只有10个,抢购的客户却有100个

 1 package com.cnblogs.yjmyzz; 2  3 public class OrderRunnable implements Runnable{ 4      5     String taskName; 6      7     public OrderRunnable(String taskName){ 8         this.taskName=taskName; 9     }10 11     private int productNum = 10;12 13     private int customerNum = 100;14 15     public void run() {16 17         for (int i = 0; i < customerNum; i++) {18             if (productNum > 0) {19                 try {20                     Thread.sleep(50);21                 } catch (InterruptedException e) {                    22                     e.printStackTrace();23                 }24                 System.out.println(taskName + " -> order success!");25                 productNum -= 1;26             }27         }28 29     }30 31 }
View Code

现在想用二个线程来处理:

 1 package com.cnblogs.yjmyzz; 2  3 public class RunnableDemo4 { 4  5     public static void main(String[] args) { 6  7         Runnable r1 = new OrderRunnable("A"); 8         Runnable r2 = new OrderRunnable("B"); 9         10         new Thread(r1).start();11         new Thread(r2).start();12         13     }14 15 }
View Code

运行结果:

A -> order success!
B -> order success!
B -> order success!
A -> order success!
B -> order success!
A -> order success!
A -> order success!
B -> order success!
B -> order success!
A -> order success!
B -> order success!
A -> order success!
A -> order success!
B -> order success!
A -> order success!
B -> order success!
A -> order success!
B -> order success!
A -> order success!
B -> order success!

显然,这个结果不正确,只有10个产品,却生成了20个订单!

正确的做法,让多个Thread共同使用一个Runnable

 1 package com.cnblogs.yjmyzz; 2  3 public class RunnableDemo5 { 4  5     public static void main(String[] args) { 6  7         Runnable r1 = new OrderRunnable("A");         8          9         new Thread(r1).start();10         new Thread(r1).start();11         12     }13 14 }
View Code

A -> order success!
A -> order success!
A -> order success!
A -> order success!
A -> order success!
A -> order success!
A -> order success!
A -> order success!
A -> order success!
A -> order success!
A -> order success!

 

五、ThreadPoolExecutor

如果有大量线程,建议使用线程池管理,下面是ThreadPoolExecutor的示例用法:

 1 package com.cnblogs.yjmyzz; 2  3 import java.util.concurrent.ArrayBlockingQueue; 4 import java.util.concurrent.ThreadPoolExecutor; 5 import java.util.concurrent.TimeUnit; 6  7 public class RunnableDemo7 { 8  9     public static void main(String[] args) {        10 11         ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 10, 1,12                 TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3));13         14         for (int i = 0; i < 6; i++) {15             threadPool.execute(new MyRunnable("R"+i, 5));16         }17 18     }19 20 }
View Code

运行结果:

R5.i=1
R0.i=1
R1.i=1
R5.i=2
R1.i=2
R0.i=2
R5.i=3
R1.i=3
R0.i=3
R5.i=4
R1.i=4
R0.i=4
R5.i=5
R0.i=5
R1.i=5
R2.i=1
R3.i=1
R4.i=1
R2.i=2
R3.i=2
R4.i=2
R2.i=3
R3.i=3
R4.i=3
R2.i=4
R4.i=4
R3.i=4
R2.i=5
R4.i=5
R3.i=5

agapple在ITeye上有一篇旧贴子,写得很好,推荐大家去看看,特别是下面这张图:

点击看大图

还有这篇 http://jiaguwen123.iteye.com/blog/1017636,也值得参考

java:多线程基础之Runnable与Thread