我们知道一个程序通常是一个进程,而一个进程可以有多个线程。
线程是不规律的在交替进行,哪个线程抢到cpu时间谁就运行。而线程运行过程中cpu也可能被其他线程抢走,然后又会继续抢cpu时间。直到线程运行结束或者所在进程已经被关掉。
Java类库已经为我们提供了一个线程基类Thread,因此创建线程非常简单。
方法一
创建两个类FirstThread和SecondThread都继承Thread类,然后重写run方法。
public class FirstThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("F --> " + i);
}
}
}
public class SecondThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("S --> " + i);
}
}
}
测试代码:
public class Test {
public static void main(String[] args) {
FirstThread ft = new FirstThread();
SecondThread st = new SecondThread();
// 用start()调用线程的run方法。
// 注意这里不能直接调用run(),否则就和普通的调用方法没区别不会启动线程
ft.start();
st.start();
}
}
部分执行结果:
F --> 0
F --> 1
F --> 2
F --> 3
F --> 4
F --> 5
F --> 6
F --> 7
F --> 8
F --> 9
F --> 10
F --> 11
F --> 12
F --> 13
S --> 0
S --> 1
S --> 2
S --> 3
S --> 4
S --> 5
S --> 6
S --> 7
F --> 14
F --> 15
F --> 16
F --> 17
F --> 18
F --> 19
S --> 8
S --> 9
S --> 10
F --> 20
运行结果可以看到两个线程不规律的交互进行互相抢cpu时间。
所以创建线程只需要继承Thread类,然后在重写的run方法里写下想在线程里执行的代码即可。注意调用时用通过调用start方法来启动线程而不能直接调用run方法。否则只是普通的调用方法并没有多线程的效果。
另外此时程序可不止两个线程。一共有四个线程,分别是Main方法所在的主线程FirstThread、SecondThread和垃圾回收线程。
方法二
因为Java只能单继承,继承了Thread类就不能再继承别的类了。这样显得不够灵活,所以实现继承更推崇的是让线程类实现Runnable接口。
以FirstThread为例:
public class FirstThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("F --> " + i);
}
}
}
测试代码要改为直接创建Thread对象但是把实现了Runnable接口的类的对象作为参数传进去。
public class Test {
public static void main(String[] args) {
Thread ft = new Thread(new FirstThread());
Thread st = new Thread(new SecondThread());
// 用start()调用线程的run方法。
// 注意这里不能直接调用run(),否则就和普通的调用方法没区别不会启动线程
ft.start();
st.start();
}
}
以上可以起到和方法一一致的效果。
实际使用中这种实现线程的方法经常会写成匿名内部类的形式,如以下这样:
new Thread() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("匿名线程 --> " + i);
}
}
}.start();
Callable和Future
以上实现线程的方式虽然简单但是有缺陷,就是run方法是void类型没有返回值,而我们有时候希望线程执行完毕后返回一个结果。
代码共享
本文代码下载:百度网盘
网友评论