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双鞋

原因在于,语句执行了,控制台没来得及打印。