Java中线程的创建有两种方式:
1. 通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中
2. 通过实现Runnable接口,实例化Thread类
在实际应用中,我们经常用到多线程,如车站的售票系统,车站的各个售票口相当于各个线程。当我们做这个系统的时候可能会想到两种方式来实现,继承Thread类或实现Runnable接口,现在看一下这两种方式实现的两种结果。
1. package com.threadtest;
2. class MyThread extends Thread{
3.
4. private int ticket = 10;
5. private String name;
6. public MyThread(String name){
7. this.name =name;
8. }
9.
10. public void run(){
11. for(int i =0;i<500;i++){
12. if(this.ticket>0){
13. System.out.println(this.name+"卖票---->"+(this.ticket--));
14. }
15. }
16. }
17.}
18.public class ThreadDemo {
19.
20.
21. public static void main(String[] args) {
22. MyThread mt1= new MyThread("一号窗口");
23. MyThread mt2= new MyThread("二号窗口");
24. MyThread mt3= new MyThread("三号窗口");
25. mt1.start();
26. mt2.start();
27. mt3.start();
28. }
29.
30.}
运行结果如下:
1. 一号窗口卖票---->10
2. 一号窗口卖票---->9
3. 二号窗口卖票---->10
4. 一号窗口卖票---->8
5. 一号窗口卖票---->7
6. 一号窗口卖票---->6
7. 三号窗口卖票---->10
8. 一号窗口卖票---->5
9. 一号窗口卖票---->4
10.一号窗口卖票---->3
11.一号窗口卖票---->2
12.一号窗口卖票---->1
13.二号窗口卖票---->9
14.二号窗口卖票---->8
15.三号窗口卖票---->9
16.三号窗口卖票---->8
17.三号窗口卖票---->7
18.三号窗口卖票---->6
19.三号窗口卖票---->5
20.三号窗口卖票---->4
21.三号窗口卖票---->3
22.三号窗口卖票---->2
23.三号窗口卖票---->1
24.二号窗口卖票---->7
25.二号窗口卖票---->6
26.二号窗口卖票---->5
27.二号窗口卖票---->4
28.二号窗口卖票---->3
29.二号窗口卖票---->2
30.二号窗口卖票---->1
通过实现Runnable接口的代码如下:
1. package com.threadtest;
2. class MyThread1 implements Runnable{
3. private int ticket =10;
4. private String name;
5. public void run(){
6. for(int i =0;i<500;i++){
7. if(this.ticket>0){
8. System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));
9. }
10. }
11. }
12.}
13.public class RunnableDemo {
14.
15.
16. public static void main(String[] args) {
17. // TODO Auto-generated method stub
18. //设计三个线程
19. MyThread1 mt = new MyThread1();
20. Thread t1 = new Thread(mt,"一号窗口");
21. Thread t2 = new Thread(mt,"二号窗口");
22. Thread t3 = new Thread(mt,"三号窗口");
23.// MyThread1 mt2 = new MyThread1();
24.// MyThread1 mt3 = new MyThread1();
25. t1.start();
26. t2.start();
27. t3.start();
28. }
29.
30.}
运行结果如下:
1. 一号窗口卖票---->10
2. 三号窗口卖票---->9
3. 三号窗口卖票---->7
4. 三号窗口卖票---->5
5. 三号窗口卖票---->4
6. 三号窗口卖票---->3
7. 三号窗口卖票---->2
8. 三号窗口卖票---->1
9. 一号窗口卖票---->8
10.二号窗口卖票---->6
为什么会出现这种结果呐。我们不妨做个比喻,其实刚的程序,
继承Thread类的,我们相当于拿出三件事即三个卖票10张的任务分别分给三个窗口,他们各做各的事各卖各的票各完成各的任务,因为MyThread继承Thread类,所以在new MyThread的时候在创建三个对象的同时创建了三个线程;
实现Runnable的, 相当于是拿出一个卖票10张得任务给三个人去共同完成,new MyThread相当于创建一个任务,然后实例化三个Thread,创建三个线程即安排三个窗口去执行。
用图表示如下:
在我们刚接触的时候可能会迷糊继承Thread类和实现Runnable接口实现多线程,其实在接触后我们会发现这完全是两个不同的实现多线程,一个是多个线程分别完成自己的任务,一个是多个线程共同完成一个任务。
其实在实现一个任务用多个线程来做也可以用继承Thread类来实现只是比较麻烦,一般我们用实现Runnable接口来实现,简洁明了。
大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应使用 Runnable 接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类(Thread)创建子类。