6.2 创建和使用线程

  创建和使用线程,就是要让这个线程完成一些特定的功能。在 Java 中,提供了java.lang. Thread类来完成多线程的编程,这个类也提供了大量的方法方便操作线程。在编写一个线程类时,可以继承自这个Thread类,完成线程的相关工作。

  如果编写的线程类要继承其他类,但Java又不支持多继承,所以Java还提供了另外一种创建线程的方式,即实现Runnable接口。

6.2.1 创建线程类

  如果线程类直接继承Thread类,其代码结构大致如下:

  1. class 类名 extends Thread{
  2. //属性
  3. //其他方法
  4. public void run(){
  5. //线程需要执行的核心代码
  6. }
  7. }

  从线程类的代码结构可以看出,一个线程的核心代码需要写在run()方法里。也就是说,当线程从就绪状态,通过调度程序分配CPU资源,进入运行状态后,执行的代码即run()方法里面的代码。

  如果线程类是实现Runnable接口的,其代码结构大致如下:

  1. class 类名 implements Runnable{
  2. //属性
  3. //其他方法
  4. public void run(){
  5. //线程需要执行的核心代码
  6. }
  7. }

  和继承Thread类非常类似,实现Runnable接口的线程类也需要编写run()方法,将线程的核心代码置于该方法中。但是 Runnable 接口并没有任何对线程的支持,因此还必须创建 Thread 类的实例,通过Thread 类的构造函数来创建线程类。

  1. 类名 对象名 = new 类名();
  2. Thread 线程对象名 = new Thread(对象名);

6.2.2 多线程使用

  下面的例子,分别使用继承Thread类和实现Runnable接口两种方式创建了两个线程类,并通过调用start()方法启动线程。具体程序代码如下:

  1. public class TestThread {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread t1 = new MyThread1();
  4. MyThread2 mt2 = new MyThread2();
  5. Thread t2 = new Thread(mt2);
  6. t1.start();
  7. t2.start();
  8. }
  9. }
  10. //继承自Thread类创建线程类
  11. class MyThread1 extends Thread {
  12. private int i = 0;
  13. //无参构造方法,调用父类构造方法设置线程名称
  14. public MyThread1(){
  15. super("我的线程1");
  16. }
  17. //通过循环判断,输出10次,每次间隔0.5秒
  18. public void run(){
  19. try{
  20. while(i < 10){
  21. System.out.println(this.getName() + "运行第" + (i+1) + "次");
  22. i++;
  23. //在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
  24. sleep(500);
  25. }
  26. }catch(Exception e){
  27. e.printStackTrace();
  28. }
  29. }
  30. }
  31. //实现Runnable接口创建线程类
  32. class MyThread2 implements Runnable{
  33. String name = "我的线程2";
  34. public void run() {
  35. System.out.println(this.name);
  36. }
  37. }

  编译、运行程序,运行结果如图6.3所示。因为程序中的注释已对程序进行了详细的描述,这里不再展开解释。

6.2 创建和使用线程 - 图1


图6.3 多线程程序

  程序中,要想启动一个线程,都是通过调用start()方法来启动的,使线程进入就绪状态,等待调度程序分配CPU资源后进入运行状态,执行run()方法里的内容。作为程序员,是不是可以直接调用run()方法,使这个线程运行起来呢?答案是:可以,但也不可以。所谓可以是指的确能直接调用run()方法执行run()方法里的代码,但这只是串行执行run()方法,并没有启动一个线程,让该线程与其他线程并行执行。

  在main()方法里的t2.start();代码后增加一句t2.run();,再次编译、运行程序,会发现“我的线程2”输出2次,其中一次是通过t2.start()方法启动线程,执行run()方法输出的,另外一次是直接调用t2.run()方法输出的。

  如果在t2.start();和t2.run();两行代码之间增加一句Thread.sleep(2000);,其含义为在2秒内让当前正在执行的线程休眠,再次编译、运行程序,其结果又如何呢?为什么会出现这样的结果呢?