1.Thread类
新建一个线程很简单,只需要new一个Java为我们封装好的Thread类,并且调用它的start()方法即可。
Thread thread = new Thread();
thread.start();
这里的start()方法会新建一个线程并让这个线程执行run()方法,但是在默认情况下,Thread类中的run()方法“什么都没干”,因此,这个线程一启动就马上结束啦,如果我们想让这个新建的线程做点什么,我们就需要继承Thread类并重写run()方法。
class Shopping extends Thread {
public void run() {
System.out.println("血拼");
}
}
public class Test {
public static void main(String[] args) {
Shopping s = new Shopping();
s.start();
}
}
这就是创建自定义线程的第一种方式,继承线程类Thread,并重写run()方法。
因为Java在继承上是单继承的,所以说继承本身也是一种宝贵的资源。但是接口是可以多实现的,因此,我们也可以使用Runnable接口来创建自定义线程。
2.Runnable接口
查看过JDK源码,我们可以发现,Runnable接口只有一个方法,也叫run()方法。
public interface Runnable {
public abstract void run();
}
而且,Thread类有这样一个构造方法:
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
它传入Runnable接口的实例,在start()方法调用时,新的线程就会执行Runnable接口实现类的run()方法。
因为实际上Thrad类中的run()方法并不是真的什么都没干(所以上面那个什么都没干是加了双引号的),下面是源码:
public void run() {
if (target != null) {
target.run();
}
}
所以说,默认的Thread类中的run()方法就是在调用Runnable接口实现类的run()方法。
class Shopping implements Runnable {
public void run() {
System.out.println(Thread.currentThread().getName() + "血拼");
}
}
public class Test {
public static void main(String[] args) {
Shopping s = new Shopping();
Thread t1 = new Thread(s);
Thread t2 = new Thread(s);
//新建一个线程,并执行run()方法
t1.start();
//再新建一个线程,并执行run()方法
t2.start();
}
}
这就是创建自定义线程的第二种方式,Shopping类实现了Runnable接口,并将其对象s传入线程对象t1、t2中,最后分别调用t1、t2的start()方法——新建线程并执行run()方法。
如果不考虑线程安全的问题,我们可以用多线程的知识来做小一个实例。
class Shopping implements Runnable {
private int num = 10;
public void run() {
while (true) {
if (num > 0) {
System.out.println(Thread.currentThread().getName() +
"抢血拼到了第" + num-- + "双鞋");
} else
break;
}
}
}
public class Test {
public static void main(String[] args) {
Shopping shopping = new Shopping();
Thread t1 = new Thread(shopping, "线程1");
Thread t2 = new Thread(shopping, "线程2");
t1.start();
t2.start();
}
}
执行结果:
线程2抢血拼到了第10双鞋
线程2抢血拼到了第9双鞋
线程1抢血拼到了第8双鞋
线程2抢血拼到了第7双鞋
线程1抢血拼到了第6双鞋
线程2抢血拼到了第5双鞋
线程1抢血拼到了第4双鞋
线程2抢血拼到了第3双鞋
线程1抢血拼到了第2双鞋
线程2抢血拼到了第1双鞋
因为是多线程程序,CPU执行哪个线程多一点完全是随机的,所以多次执行的打印结果可能会有不同。
还有可能出现这种情况:
线程1抢血拼到了第10双鞋
线程1抢血拼到了第9双鞋
线程1抢血拼到了第7双鞋
线程1抢血拼到了第6双鞋
线程1抢血拼到了第5双鞋
线程1抢血拼到了第4双鞋
线程1抢血拼到了第3双鞋
线程1抢血拼到了第2双鞋
线程1抢血拼到了第1双鞋
线程2抢血拼到了第8双鞋
原因在于,语句执行了,控制台没来得及打印。