从JDK1.5开始,Java提供了3种方式来创建,启动多线程:
继承Thread类来创建线程类,重写run()方法作为线程执行体;
实现Runnable接口来创建线程类,重写run()方法作为线程执行体;
实现Callable接口来创建线程类,重写call()方法作为线程执行体。
其中,第1种方式的效果最差,它有2种坏处:
线程类继承了Thread类,无法再继承其他父类;
因为每条线程都是一个Thread子类的实例,因此多个线程之间共享数据比较麻烦。
对于第2种和第3种方式,它们的本质是一样的,只是Callable接口里包含的call()方法既可以声明抛出异常,也可以拥有返回值。
除此之外,如果采用继承Thread类的方式来创建多线程,程序会有一个潜在的危险,如下:
public class InvokeRun extends Thread{
private int i;
public void run(){
for(;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
public static void main(String[] args){
for(inti=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
new InvokeRun().run();
new InvokeRun().run();
}
}
}
}
main 0
main 1
main 2
main 3
main 4
main 5
main 6
main 7
main 8
main 9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
main20
main 0
main 1
main 2
main 3
main 4
main 5
main 6
main 7
main 8
main 9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
main20
main21
main22
main23
main24
main25
main26
main27
main28
main29
main30
main31
main32
main33
main34
main35
main36
main37
main38
main39
main40
main41
main42
main43
main44
main45
main46
main47
main48
main49
main50
main51
main52
main53
main54
main55
main56
main57
main58
main59
main60
main61
main62
main63
main64
main65
main66
main67
main68
main69
main70
main71
main72
main73
main74
main75
main76
main77
main78
main79
main80
main81
main82
main83
main84
main85
main86
main87
main88
main89
main90
main91
main92
main93
main94
main95
main96
main97
main98
main99
main 0
main 1
main 2
main 3
main 4
main 5
main 6
main 7
main 8
main 9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
main20
main21
main22
main23
main24
main25
main26
main27
main28
main29
main30
main31
main32
main33
main34
main35
main36
main37
main38
main39
main40
main41
main42
main43
main44
main45
main46
main47
main48
main49
main50
main51
main52
main53
main54
main55
main56
main57
main58
main59
main60
main61
main62
main63
main64
main65
main66
main67
main68
main69
main70
main71
main72
main73
main74
main75
main76
main77
main78
main79
main80
main81
main82
main83
main84
main85
main86
main87
main88
main89
main90
main91
main92
main93
main94
main95
main96
main97
main98
main99
main21
main22
main23
main24
main25
main26
main27
main28
main29
main30
main31
main32
main33
main34
main35
main36
main37
main38
main39
main40
main41
main42
main43
main44
main45
main46
main47
main48
main49
main50
main51
main52
main53
main54
main55
main56
main57
main58
main59
main60
main61
main62
main63
main64
main65
main66
main67
main68
main69
main70
main71
main72
main73
main74
main75
main76
main77
main78
main79
main80
main81
main82
main83
main84
main85
main86
main87
main88
main89
main90
main91
main92
main93
main94
main95
main96
main97
main98
main99
上面程序试图在主线程中i==20时创建并启动2条新线程。编译该程序,一切正常,运行该程序,发现该程序只有一个线程――main线程。程序执行的大致过程如下:
输出main20之后,又重新开始输出main0.
从main0一直输出到main99,再次从main0开始输出。
再次从main0一直输出到main99,再次从main22开始输出,知道main99结束。
上面的程序始终只有一条线程,并没有启动任何新线程,关键是因为调用了线程对象的run()方法,而不是start()方法――启动线程应该使用start()方法,而不是run()方法。
如果程序从未调用线程对象的start()方法来启动它,那么这个线程对象将一直处于新建状态,它永远也不会作为线程获得执行的机会,它只是一个普通的java对象。当程序调用线程对象的run()方法时,与调用普通java对象的普通方法并无任何区别,因此绝对不会启动一条新线程。
main 0
main 1
main 2
main 3
main 4
main 5
main 6
main 7
main 8
main 9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
main20
main21
main22
main23
Thread-10
Thread-11
Thread-12
main24
main25
main26
main27
main28
Thread-00
Thread-01
Thread-02
Thread-03
Thread-04
Thread-05
Thread-06
Thread-07
Thread-08
Thread-09
Thread-010
Thread-011
main29
Thread-13
Thread-14
main30
Thread-012
Thread-013
main31
Thread-15
Thread-16
main32
Thread-014
Thread-015
Thread-016
main33
Thread-17
main34
Thread-017
main35
Thread-18
main36
Thread-018
main37
Thread-19
main38
Thread-019
main39
Thread-110
main40
Thread-020
main41
main42
Thread-111
main43
Thread-021
main44
Thread-112
main45
Thread-022
main46
Thread-113
main47
Thread-023
Thread-024
Thread-025
Thread-026
Thread-027
Thread-028
main48
Thread-114
main49
Thread-029
main50
Thread-115
main51
Thread-030
main52
Thread-116
main53
Thread-031
main54
Thread-117
main55
Thread-032
main56
Thread-118
main57
Thread-033
main58
Thread-119
main59
Thread-034
main60
Thread-120
main61
Thread-035
main62
main63
Thread-121
Thread-122
Thread-123
main64
Thread-036
main65
Thread-124
Thread-125
main66
Thread-037
main67
main68
Thread-126
main69
main70
Thread-038
main71
main72
Thread-127
main73
Thread-039
main74
Thread-128
main75
Thread-040
Thread-041
main76
Thread-129
main77
Thread-042
Thread-043
main78
Thread-130
Thread-131
main79
Thread-044
main80
Thread-132
main81
Thread-045
main82
Thread-133
main83
Thread-046
main84
Thread-134
main85
Thread-047
main86
Thread-135
main87
Thread-048
main88
Thread-136
main89
main90
Thread-049
main91
main92
Thread-137
main93
Thread-050
Thread-051
main94
Thread-138
main95
Thread-052
main96
Thread-139
Thread-140
main97
Thread-053
main98
Thread-141
main99
Thread-054
Thread-055
Thread-056
Thread-057
Thread-058
Thread-142
Thread-059
Thread-060
Thread-143
Thread-061
Thread-144
Thread-062
Thread-145
Thread-146
Thread-063
Thread-147
Thread-064
Thread-148
Thread-065
Thread-149
Thread-066
Thread-150
Thread-067
Thread-151
Thread-068
Thread-152
Thread-069
Thread-153
Thread-070
Thread-154
Thread-071
Thread-155
Thread-072
Thread-156
Thread-073
Thread-157
Thread-074
Thread-158
Thread-075
Thread-159
Thread-076
Thread-160
Thread-077
Thread-078
Thread-079
Thread-161
Thread-080
Thread-162
Thread-081
Thread-163
Thread-082
Thread-164
Thread-083
Thread-165
Thread-084
Thread-166
Thread-085
Thread-086
Thread-167
Thread-087
Thread-168
Thread-088
Thread-169
Thread-089
Thread-170
Thread-171
Thread-090
Thread-172
Thread-091
Thread-092
Thread-173
Thread-093
Thread-174
Thread-094
Thread-175
Thread-095
Thread-176
Thread-096
Thread-177
Thread-097
Thread-178
Thread-098
Thread-179
Thread-099
Thread-180
Thread-181
Thread-182
Thread-183
Thread-184
Thread-185
Thread-186
Thread-187
Thread-188
Thread-189
Thread-190
Thread-191
Thread-192
Thread-193
Thread-194
Thread-195
Thread-196
Thread-197
Thread-198
Thread-199