1、继承Thread
首先创建一个类继承Thread类,然后重写run()方法。 run方法就是线程要执行的任务方法。
run方法里面的代码就是一条新的执行路径。执行路径的触发方式,是通过Thread对象的start()方法启动任务。
main方法为主线程,其他都为分支线程,Thread类的线程与main方法是并发运行的,时间分配是抢占式分配。
程序开启,main线程开启,当所有线程执行完之后程序结束。
每个线程都拥有自己的栈空间,共用一份堆内存。
由一个线程调用的方法,那么这个方法也会执行在这个线程里面。
实现的完整代码如下:
首先创建一个MyThread类:其实就是子线程。
package ceshi;
public class MyThread extends Thread{
public void run(){
for (int i = 0;i<5;i++){
System.out.println(i);
}
}
}
然后再在main方法里面MyThread类的对象调用start方法:
package ceshi;
public class TestIO {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
for (int i = 0;i<5;i++){
System.out.println("main"+i);
}
}
}
两个线程的输出可以看出两个线程对时间是抢占式分配,并不是均分。结果如下:
0
1
main0
2
3
4
main1
main2
main3
main4
接下来我们试下使用匿名内部类的 方式来实现多线程,还是Thread的方式:
public class Demo2 {
public static void main(String[] args) {
//使用匿名内部类的方法,任然还是要重写run方法。直接调用start开始线程
new Thread(){
public void run(){
for (int i = 0;i<5;i++){
System.out.println(i);
}
}
}.start();
for (int i = 0;i<5;i++){
System.out.println("main"+i);
}
}
}
运行结果:
main0
0
1
2
3
4
main1
main2
main3
main4
与上面重写一个Thread类的子类其实是一样的。
2、第二种常用的开启多线程方式
实现Runnable接口
自己创建一个类实现接口Runnable
重写run()方法,在方法体中实现线程的任务。
然后在main方法里面还得实现Thread对象。
第一步:创建一个任务对象即是自己创建的类的对象;第二步:创建一个线程Thread的对象,并为其分配任务;第三步:执行这个线程start方法
实现Runnable与继承Thread相比有如下的优势:1. 通过创建任务给线程分配的方式来实现的多线程,更适合多个线程同时执行相同任务的情况。2. 可以避免单继承所带来的局限性。3. 任务与线程本身是分离的,提高了程序的健壮性。4. 后续学习的线程池技术,接受Runnable类型的任务,而不接受Thread类型的线程。
完整代码如下参考:
public class Demo3 {
public static void main(String[] args) {
// 先创建一个MyThread实现的接口的对象
MyThread myThread = new MyThread();
// 然后再创建Thread的对象,参口应为接口的实现类的对象myThread,
Thread thread = new Thread(myThread);
// 调用start方法
thread.start();
for (int i = 0;i<5;i++){
System.out.println("main"+i);
}
}
}
结果:
main0
main1
0
1
2
3
4
main2
main3
main4