有两种方法可以创建新的执行线程。
一种是将一个类声明为 Thread 的子类。该子类应重写类 Thread 的 run 方法。然后可以分配并启动子类的实例。
注意运行线程的时候调用start方法,这个线程就会调用自己的run方法。
例如,计算大于指定值的素数的线程可以编写如下:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
下面的代码将创建一个线程并开始运行:
PrimeThread p = new PrimeThread(143);
p.start();
我们来探究一下主线程和子线程的执行
当我们运行这个代码,会发现每次基本都不一样
缺点:这个类已经继承了Thread类,不能再继承其他类
注意:
- 启动线程必须调用start方法,不是调用run方法
- 不要把主线程的任务放在子线程之前
解释:
- 如果调用的是run方法,那么本质上相当于调用了一个类的方法,没有开辟一个新的线程,且每次运行的结果都是一样的
- 如果把主任务的任务放在子线程之前,那么会先执行主线程的任务,结果还是每次一样,失去了多线程的意义
创建线程的另一种方法是声明一个实现 Runnable 接口的类。然后该类实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为参数传递并启动。另一种风格的相同示例如下所示:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
注意这种方法创建的只是一个任务对象,你要需要创建一个线程对象来实现
运行代码:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
值得注意的是,我们这个类是实现Runable接口,不是继承类
看一下Runable的定义
public interface Runnable {
/**
* Runs this operation.
*/
void run();
}
alt + enter可以快速补充抽象方法
要把任务对象交给线程对象Thread
MyRunable t1 = new MyRunable();
new Thread(t1).start();
创建线程的匿名
// 匿名任务类,作为任务类
Runnable target = new Runnable() {
@Override
public void run() {
for(int i=1;i<=5;i++){
System.out.println("子线程1:" + i);
}
}
};
new Thread(target).start();
简化写法
new Thread(new Runnable() {
@Override
public void run() {
for(int i=1;i<=5;i++){
System.out.println("子线程1:" + i);
}
}
}).start();
再次简化
new Thread(() ->{
for(int i=1;i<=5;i++){
System.out.println("子线程1:" + i);
}
}).start();