创建一个线程主要有两个方法:实现Runnable接口和继承Thread类。虽然Thread类底层也实现了Runnable接口,但在使用的时候两者还是有很大差别。
1. 继承Runnable接口:
public class TestRunnable implements Runnable{ private String name; //给线程一个名称,方便标识 public TestRunnable(String name){ this.name = name; } @Override public void run(){ for(int i=0; i<10; i++){ System.out.println(name+"正在运行:"+" "+i); } } public static void main(String[] args){ TestRunnable t1 = new TestRunnable("A"); TestRunnable t2 = new TestRunnable("B"); Thread thread1 = new Thread(t1); //用实现Runna接口的对象来创建线程 Thread thread2 = new Thread(t2); thread1.start(); thread2.start(); } }运行结果为:
A正在运行: 0
B正在运行: 0
A正在运行: 1
B正在运行: 1
A正在运行: 2
B正在运行: 2
A正在运行: 3
A正在运行: 4
B正在运行: 3
A正在运行: 5
B正在运行: 4
A正在运行: 6
B正在运行: 5
A正在运行: 7
B正在运行: 6
A正在运行: 8
B正在运行: 7
A正在运行: 9
B正在运行: 8
B正在运行: 9
再运行一次,发现结果不一样:
A正在运行: 0
B正在运行: 0
A正在运行: 1
B正在运行: 1
A正在运行: 2
B正在运行: 2
A正在运行: 3
A正在运行: 4
A正在运行: 5
A正在运行: 6
A正在运行: 7
A正在运行: 8
A正在运行: 9
B正在运行: 3
B正在运行: 4
B正在运行: 5
B正在运行: 6
B正在运行: 7
B正在运行: 8
B正在运行: 9
这是因为每次在运行中,线程都要抢夺CPU资源,由于优先级不同,最终执行的顺序和结果也不同。
2. 继承Thread类:
public class TestThread extends Thread{
private String name;
public TestThread(String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(name + "正在运行 " + i);
}
}
public static void main(String[] args) {
TestThread h1 = new TestThread("A");
TestThread h2 = new TestThread("B");
h1.start();
h2.start();
}
}
运行结果:
A正在运行 0
B正在运行 0
A正在运行 1
B正在运行 1
A正在运行 2
B正在运行 2
A正在运行 3
B正在运行 3
A正在运行 4
B正在运行 4
A正在运行 5
B正在运行 5
A正在运行 6
B正在运行 6
A正在运行 7
B正在运行 7
A正在运行 8
A正在运行 9
B正在运行 8
B正在运行 9
3. Thread与Runnable比较:
看上去Thread的写法更简洁,只需要创建对象并start就好。如果不使用公共资源,确实用Thread更方便。但如果有一个变量是多个线程间共享的,怎么办?
在TestThread对象中增加一个字段count。
public class TestThread extends Thread{
private String name;
private int count = 10;
public TestThread(String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 10; i++) {
--count;
System.out.println(name + "正在运行 " + i + " count还有"+count);
}
}
public static void main(String[] args) {
TestThread h1 = new TestThread("A");
TestThread h2 = new TestThread("B");
h1.start();
h2.start();
}
}
结果怎样可以猜出来,这根本是两个对象,各计算各的。
A正在运行 0 count还有9
B正在运行 0 count还有9
B正在运行 1 count还有8
B正在运行 2 count还有7
B正在运行 3 count还有6
B正在运行 4 count还有5
B正在运行 5 count还有4
B正在运行 6 count还有3
B正在运行 7 count还有2
B正在运行 8 count还有1
A正在运行 1 count还有8
B正在运行 9 count还有0
A正在运行 2 count还有7
A正在运行 3 count还有6
A正在运行 4 count还有5
A正在运行 5 count还有4
A正在运行 6 count还有3
A正在运行 7 count还有2
A正在运行 8 count还有1
A正在运行 9 count还有0
那如果换成static类型的变量呢?static为类的所有对象维护一个公共变量。
A正在运行 0 count还有9
B正在运行 0 count还有8
A正在运行 1 count还有7
B正在运行 1 count还有6
A正在运行 2 count还有5
B正在运行 2 count还有4
A正在运行 3 count还有3
B正在运行 3 count还有2
B正在运行 4 count还有0
B正在运行 5 count还有-1
B正在运行 6 count还有-2
B正在运行 7 count还有-3
B正在运行 8 count还有-4
B正在运行 9 count还有-5
A正在运行 4 count还有1
A正在运行 5 count还有-6
A正在运行 6 count还有-7
A正在运行 7 count还有-8
A正在运行 8 count还有-9
A正在运行 9 count还有-10
乍一看似乎不错,但如果仔细观察,会发现顺序和数字根本不对。所以用Thread不能正确的实现资源共享。