手记

Java多线程的使用(二)

今天来讲讲Java如何创建一个线程。

大多数情况下,通过实例化一个Thread对象来创建一个线程,Java定义了两种方式:

  • 实现Runnable接口

  • 继承Thread类

实现Runnable接口

创建线程的最简单的方法就是创建一个Runnable口的类。Runnable抽象了一个执行代码单元。为实现Runnable接口,一个类仅需实现一个run()的简单方法,在run()方法中可以定义代码来构建新的线程。创建一个线程必须理解下面这段话:

run()方法能够让主线程那样调用其他方法,引用其他类,声明变量。仅有的不同的是run()方法在程序中确立另一个并发的线程执行入口。当run()方法运行完毕时,该线程结束。

在你已经创建了实现Runnable接口的类以后,你要在类内部实例化一个Thread类的对象。

Thread(Runnable threadOb,String threadName)

该构造函数中,threadOb时一个实现Runnable接口的实现类,threadName参数则是你新建线程的线程名称,这定义了线程执行的起点。

建立了新的线程,它并不能运行,需要调用start方法来执行线程的run()方法。本质上,start()方法执行的是一个对run()的调用。

  1. public class Test1 {  

  2.   

  3.     public static void main(String[] args) throws InterruptedException {  

  4.         new XkThread();  

  5.         try {  

  6.             for(int i=1;i<=5;i++){  

  7.                 Thread.currentThread().sleep(1000);//让当前线程睡眠1秒      

  8.                 System.out.println("大家好,我是主线程:"+i);  

  9.             }  

  10.             //需要捕获sleep()方法可能抛出的异常  

  11.         } catch (InterruptedException e) {  

  12.             e.printStackTrace();  

  13.         }  

  14.     }  

  15. }  

  16. class XkThread implements Runnable {  

  17.     private Thread th;  

  18.   

  19.     public XkThread() {  

  20.         th=new Thread(this);  

  21.         System.out.println("开始调用run()方法");  

  22.         th.start();//调用run()方法  

  23.     }  

  24.     @Override  

  25.     public void run() {  

  26.         try {  

  27.             for(int i=1;i<=5;i++){  

  28.                 th.sleep(1000);//让线程睡眠1秒      

  29.                 System.out.println("大家好,我是子线程:"+i);  

  30.             }  

  31.             //需要捕获sleep()方法可能抛出的异常  

  32.         } catch (InterruptedException e) {  

  33.             e.printStackTrace();  

  34.         }  

  35.           

  36.     }  

  37.       

  38. }  

在NewThread中构造函数中,新的Thread对象由下面语句创建:

  1. th=new Thread(this);  

通过前面的语句this表明了在this对象中你想要新的线程调用run()方法。然后start()被调用,以run()方法为开始启动了线程的执行。这使子线程for循环开始执行。调用start()方法之后,NewThread的构造函数返回到main()。当主线程被恢复,主线程开始执行自己的for循环。两个线程同时运行,共享CPU,直到它们的循环结束。

运行结果:

  1. 开始调用run()方法  

  2. 大家好,我是主线程:1  

  3. 大家好,我是子线程:1  

  4. 大家好,我是子线程:2  

  5. 大家好,我是主线程:2  

  6. 大家好,我是子线程:3  

  7. 大家好,我是主线程:3  

  8. //省略  

继承Thread类

创建线程的另一个途径就是继承Thread类,然后创建子类的实例。当一个类继承Thread类时,它必须重写run()方法,这个run()方法时新线程的入口。它也必须调用start()方法来启用新线程执行。

  1. public class Test2 {  

  2.   

  3.     public static void main(String[] args) {  

  4.         new MyThread("child Thread");  

  5.         System.out.println("开始执行主线程的for循环");  

  6.         try {  

  7.             for(int i=1;i<=5;i++){  

  8.                 Thread.currentThread().sleep(1000);//让主线程睡眠1秒     

  9.                 System.out.println("大家好,我是主线程:"+i);  

  10.             }  

  11.             //需要捕获sleep()方法可能抛出的异常  

  12.         } catch (InterruptedException e) {  

  13.             e.printStackTrace();  

  14.         }  

  15.     }  

  16. }  

  17. class MyThread extends Thread{  

  18.   

  19.     public MyThread(String threadName) {  

  20.         super(threadName);  

  21.         System.out.println("开始调用start()方法");  

  22.         start();  

  23.     }  

  24.       

  25.     @Override  

  26.     public void run() {  

  27.         System.out.println("开始执行子线程的for循环");  

  28.         try {  

  29.             for(int i=1;i<=5;i++){  

  30.                 sleep(500);//让子线程睡眠0.5秒   

  31.                 System.out.println("大家好,我是子线程:"+i);  

  32.             }  

  33.             //需要捕获sleep()方法可能抛出的异常  

  34.         } catch (InterruptedException e) {  

  35.             e.printStackTrace();  

  36.         }  

  37.     }  

  38.       

  39. }  

创建一个子线程MtThread,在构造函数中调用start()方法启动子线程,然后主线程也继续运行,为了让主线程最后结束,在这里我让子线程睡眠时间为0.5秒,主线程睡眠时间为1秒,这样子总可以让主线程最后结束。

运行结果:

  1. 开始调用start()方法  

  2. 开始执行主线程的for循环  

  3. 开始执行子线程的for循环  

  4. 大家好,我是子线程:1  

  5. 大家好,我是子线程:2  

  6. 大家好,我是主线程:1  

  7. 大家好,我是子线程:3  

  8. 大家好,我是主线程:2  

  9. 大家好,我是子线程:4  

  10. 大家好,我是子线程:5  

  11. 大家好,我是主线程:3  

  12. 大家好,我是主线程:4  

  13. 大家好,我是主线程:5  

最后

到这里,你一定很奇怪为什么Java有两种创建子线程的方法呢?哪一种更好呢?所有的问题都归于一点,Thread类定义了多种方法可以被子类重载。对于所有的方法,唯一的必须重写的是run()方法。而实现Runnable接口也只需要重写run()方法。因此,如果你不重载Thread的其他方法,最好是实现Runnable接口。当然了,这得看个人习惯。

原文出处

0人推荐
随时随地看视频
慕课网APP