几种创建线程方式Thread类和Runnable接口

Posted shadowlovesunshine

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了几种创建线程方式Thread类和Runnable接口相关的知识,希望对你有一定的参考价值。

对于很多想学习java的人来说,经常听别人说线程难,其实真正理解了线程后,一点都不会觉得线程难,这里我为大家梳理下线程的创建方式吧.

一.线程的创建方式有三种

1.继承Thread类

2.实现Runnable接口

3.实现Callable接口(返回结果并且可能抛出异常的任务).

如果采用实现Callable接口接口的方式,返回结果并且可能抛出异常的任务,不利于开发,这里就不给大家介绍了.这里咋们主要说说采用继承Thread类和实现Runnable接口的方式来创建线程.

1.继承Thread类的方式

Java使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。Java中通过继承Thread类来创建启动多线程的步骤如下:

  1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。

  2. 创建Thread子类的实例,即创建了线程对象

  3. 调用线程对象的start()方法来启动该线程

代码如下:

测试类:

/*
    1)定义类继承Thread,重写run方法
    2)创建线程对象
    3)进行调用线程的start方法进行开启线程

 */
public class Demo01 {
    public static void main(String[] args) {

        MyThread m = new MyThread();
        m.start();

        for (int i = 0; i < 100; i++) {
            System.out.println("小强:" + i);
        }

    }
}

创建类来实现Thread

public class MyThread extends Thread {
    @Override
    public void run() {
        //多线程处理的任务
        for (int i = 0; i < 100; i++) {
            System.out.println("旺财:" + i);
        }
    }
}

看了上面的代码,你可能会问,线程对象是如何创建的,线程里面有哪些方法呢?下面就来说说怎么创建线程对象.

通过查看API我们看到了lang包下的Thread类,是非抽象的,还有构造方法,那是不是就是可以直接用Thread类的构造方法来创建对象呢?答案是:不可以!!!

记住:

Thread类的构造方法不是为创建线程而定的,是给子类使用的!!!

线程常用的方法:
1. public String getName():获取当前线程名称。
2. public void start():导致此线程开始执行; Java虚拟机调用此线程的run方法。
3. public void run():此线程要执行的任务在此处定义代码。
4. public static void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
5. public static Thread currentThread():返回对当前正在执行的线程对象的引用。

线程的执行步骤:线程执行,开启了线程,JVM调用其run方法来执行任务。

public class MyThread2 extends Thread {
    public MyThread2(){
        super(); // public Thread()
    }

    public MyThread2(String name) {
        super(name);/// public Thread(String name)
    }


    @Override
    public void run() {
        //如果没有给线程起名:默认 Thread-x
        String name = getName(); //获取线程的名字
        System.out.println(name +"线程执行起来");
    }
}

测试类

public class Demo02 {
    public static void main(String[] args) {
        //Thread直接创建对象,Thread(),Thread(String name)
        Thread mt1 = new Thread();
        mt1.start();

        MyThread2 mt2 = new MyThread2();
        mt2.start();

        MyThread2 mt3 = new MyThread2("小强");
        mt3.start();


        //public static Thread currentThread():返回当前方法运行的线程对象
        Thread thread = Thread.currentThread();
        String name = thread.getName();
        System.out.println("main方法执行的线程名字: " + name);

        //public static void sleep(long mills)
        for (int i = 0; i < 10; i++) {
            System.out.println(i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

 Thread类API查询:

技术图片

 

2.实现Runnable接口

首先我们来看看API是怎么说的

技术图片

由API中的介绍,我们采用java.lang.Runnable也是非常常见的一种,我们不用继承Thread类,只需要重写run方法即可。

  1. public Thread(Runnable target):分配一个带有指定目标新的线程对象。

  2. public Thread(Runnable target,String name):分配一个带有指定目标新的线程对象并指定名字。

一般使用步骤:
1)先创建任务【Runnable的对象】
2)借助含有Runnable参数的Thread构造方法,进行创建线程
3)调用线程的start方法开启线程

public class Demo01 {
    public static void main(String[] args) {
        Runnable runnable = new MyRunnable();
        //1. public Thread(Runnable target):分配一个带有指定目标新的线程对象。
        Thread mth1 = new Thread(runnable);
        mth1.start();

        //2. public Thread(Runnable target,String name):分配一个带有指定目标新的线程对象并指定名字。

        Thread mth2 = new Thread(runnable, "旺财");
        mth2.start();

        //3. 匿名内部类实现
        Runnable target = new Runnable() {
            @Override
            public void run() {
                Thread thread = Thread.currentThread();
                String name = thread.getName();

                System.out.println(name+"线程执行run方法【匿名内部类实现】");
            }
        };

        new Thread(target).start();
        new Thread(target,"旺财").start();

    }
}

通过实现Runnable接口,使得该类有了多线程类的特征。run()方法是多线程程序的一个执行目标。所有的多线程代码都在run方法里面。Thread类实际上也是实现了Runnable接口的类。

在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。

小结

多线程代码都是通过调用Thread的start()方法来运行的。因此,不管是继承Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础。

Runnable对象仅仅作为Thread对象的target,Runnable实现类里包含的run()方法仅作为线程执行体。而实际的线程对象依然是Thread实例,只是该Thread线程负责执行其target的run()方法。

3.Thread和Runnable的区别

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

总结:

实现Runnable接口比继承Thread类所具有的优势:

  1. 适合多个相同的程序代码的线程去共享同一个资源。

  2. 可以避免java中的单继承的局限性。

  3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。

  4. 线程池只能放入实现Runnable或Callable类线程,不能直接放入继承Thread的类。

扩充:在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM其实在就是在操作系统中启动了一个进程。

 

以上是关于几种创建线程方式Thread类和Runnable接口的主要内容,如果未能解决你的问题,请参考以下文章

创建线程有哪几种方式

多线程:Thread类和Runnable接口

继承Thread类和实现Runnable接口创建的线程对于实例变量和类变量的共享

继承Thread类和实现Runnable接口创建的线程对于实例变量和类变量的共享

Java中的线程

线程的创建方式比较