在Java中创建线程有两种方法:继承Thread类和实现Runnable接口。
一、继承Thread类创建线程类(Thread类已经实现了 Runnable接口)
1、Thread类的构造方法有8个,但常用的只有4个,分别为:
Thread类中的两个最主要的方法:
(1)run()—包含线程运行时所执行的代码,即线程需要完成的任务,是线程执行体。
(2)start()—用于启动线程。
2、通过继承Thread类来创建并启动多线程的步骤:
(1)定义Thread类的子类,并覆盖该类的run()方法。
(2)创建Thread子类的实例,即创建线程对象。
(3)用线程对象的start()方法来启动该线程。
例程:
Java 代码
1. public class Thread1 extends Thread{
2. public void run(){
3. System.out.println(this.getName());
4. }
5. public static void main(String args[]){
6. System.out.println(Thread.currentThread().getName());
7. Thread1 thread1 = new Thread1();
8. Thread1 thread2 = new Thread1();
9. thread1.start();
10. thread2.start();
11. }
12. }
public class Thread1 extends Thread{
public void run(){
System.out.println(this.getName());
}
public static void main(String args[]){
System.out.println(Thread.currentThread().getName());
Thread1 thread1 = new Thread1();
Thread1 thread2 = new Thread1();
thread1.start();
thread2.start();
}
}
程序的运行结果如下:
main
Thread-0
Thread-1
注意:程序中两条线程并发执行时,每次的执行结果是会变化的。这是因为,如果多个没有同步约束关系的线程并发执行时,调度线程将不能保证哪个线程先执行及其持续的时间,在不同平台上,或在同一平台上不同时刻的多次运行可能会得到不同的结果。
Java中对于线程启动后唯一的能够保障的就是:“每个线程都将启动,每个线程都会执行结束”。但谁会先执行谁会后执行,将没有保障,也就是说,就算一个线程在另一个线程之前启动,也无法保障该线程一定在另一个线程之前执行完毕。
程序分析如下:
(1)任何一个Java程序都必须有一个主线程。主线程的线程执行体不是由run()方法来确定的,而是由main()方法来确定的:main()方法的方法体代表主线程的线程执行体。
(1)上面程序用到线程的两个方法:
Thread.currentThread():currentThread()是Thread类的静态方法,该方法总是返回当前正在执行的线程对象的引用。
getName():该方法是Thread类的实例方法,该方法返回调用该方法的线程的名字。
(3)程序可以通过setName(String name)方法为线程设置名字,也可以通过getName()方法返回指定线程的名字。在默认情况下,主线程的名字为main,用户启动的多条线程的名字依次为:Thread-0、Thread-1、Thread-2、……、Thread-n等。
(4)一个线程只能被启动一次。否则会抛出java.lang.IllegalThreadStateException异常。
二、实现Runnable接口创建线程类
实现Runnable接口的类必须使用Thread类的实例才能创建线程。通过实现Runnable接口来创建并启动多线程的步骤:
(1)定义Runnable接口的实现类,并实现该接口的run()方法。
(2)创建Runnable实现类的实例,然后将该实例作为参数传入Thread类的构造方法来创建Thread对象。
(3)用线程对象的start()方法来启动该线程。
例程:
Java 代码
1. public class MyRunnable implements Runnable{
2. public void run(){
3. System.out.println(Thread.currentThread().getName());
4. }
5. public static void main(String args[]){
6. MyRunnable r1 = new MyRunnable();
7. MyRunnable r2 = new MyRunnable();
8. MyRunnable r3 = new MyRunnable();
9. Thread thread1 = new Thread(r1,"MyThread1");
10. Thread thread2 = new Thread(r2);
11. thread2.setName("MyThread2");
12. Thread thread3 = new Thread(r3);
13. thread1.start();
14. thread2.start();
15. thread3.start();
16. }
17. }
public class MyRunnable implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getName());
}
public static void main(String args[]){
MyRunnable r1 = new MyRunnable();
MyRunnable r2 = new MyRunnable();
MyRunnable r3 = new MyRunnable();
Thread thread1 = new Thread(r1,"MyThread1");
Thread thread2 = new Thread(r2);
thread2.setName("MyThread2");
Thread thread3 = new Thread(r3);
thread1.start();
thread2.start();
thread3.start();
}
}
三、两种创建线程方式的比较
采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标(target)对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。
|