Java中如何使用Thread和Runnable创建的线程

导读:本篇文章讲解 Java中如何使用Thread和Runnable创建的线程,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

前言

我们都知道通过继承Thread和实现Runnable接口都能创建线程,那么他们有什么区别呢?

继承Thread创建线程

通过extends关键字继承Thread然后覆盖其run方法就可以实现一个自己的线程。启动的时候只需要调用thread的start方法就可以了。

public class ExtendThreadDemo extends Thread {
    //定一个线程的名称
    private String name;

    //带参数的构造方法
    ExtendThreadDemo(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println("[ExtendThreadDemo]我是线程:ExtendThreadDemo-" + name);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            ExtendThreadDemo threadDemo = new ExtendThreadDemo(String.valueOf(i));
            threadDemo.start();
        }
    }
}

打印日志:

[ExtendThreadDemo]我是线程:ExtendThreadDemo-0
[ExtendThreadDemo]我是线程:ExtendThreadDemo-1
[ExtendThreadDemo]我是线程:ExtendThreadDemo-2
[ExtendThreadDemo]我是线程:ExtendThreadDemo-4
[ExtendThreadDemo]我是线程:ExtendThreadDemo-3

从日志中我们可以看出,一共创建了5个线程这5个线程是异步执行的。

实现Runnable接口创建线程

通过implements关键字实现Runnable接口并且实现里面的run方法来创建线程。注意这里启动线程的时候需要使用new Thread(Runable).start()方法。

public class RunnableThreadDemo implements Runnable {
    //定一个线程的名称
    private String name;

    //带参数的构造方法
    RunnableThreadDemo(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println("[RunnableThreadDemo]我是线程:RunnableThreadDemo" + name);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            RunnableThreadDemo threadDemo = new RunnableThreadDemo(String.valueOf(i));
            new Thread(threadDemo).start();
        }
    }
}

打印日志:

[RunnableThreadDemo]我是线程:RunnableThreadDemo3
[RunnableThreadDemo]我是线程:RunnableThreadDemo4
[RunnableThreadDemo]我是线程:RunnableThreadDemo2
[RunnableThreadDemo]我是线程:RunnableThreadDemo1
[RunnableThreadDemo]我是线程:RunnableThreadDemo0

我们可以看出通过实现Runable接口的方式同样可以达到异步执行线程的目的。

线程run方法和start方法区别

线程启动使用的是start()方法,其实start方法里也是调用了run()方法,他们之间的区别是什么?
我们做一个测试,将上面的ExtendThreadDemo类里面的main方法稍作修改为:

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            ExtendThreadDemo threadDemo = new ExtendThreadDemo(String.valueOf(i));
            threadDemo.run();
        }
    }

也就是将里面的start()方法换成了run()方法。打印结果:

[ExtendThreadDemo]我是线程:ExtendThreadDemo-0
[ExtendThreadDemo]我是线程:ExtendThreadDemo-1
[ExtendThreadDemo]我是线程:ExtendThreadDemo-2
[ExtendThreadDemo]我是线程:ExtendThreadDemo-3
[ExtendThreadDemo]我是线程:ExtendThreadDemo-4

这里线程打印结果的顺序是我们同步启动线程的顺序(无论试多少次都是这个结果),这说明线程没有异步启动,而是同步执行了里面的run()方法而已。

start方法源码分析

    public synchronized void start() {
        //(1)判断状态是否是0。0代表是新建状态NEW,否则抛出异常
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        //(2)将线程添加到线程组列表中
        group.add(this);
        //(3)将是否进入就绪态设置为false
        boolean started = false;
        try {
        	//(4)调用private native void start0();方法,推测方法就是请求CPU分配时间片方法
            start0();
            //(5)调用native方法成功,将状态修改为true
            started = true;
        } finally {
            try {
            	//(6)调用native方法失败,将回退操作
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

第(4)这里调用了Java的native方法为:

    private native void start0();

所谓的navtiv方法简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。

引用:Java的native方法
https://blog.csdn.net/wike163/article/details/6635321

Thread和Runable创建线程的区别

简单写一个测试类CreateThreadTest里面的线程都使用内部类实现:

public class CreateThreadTest {
    //内部类继承Thread创建线程
    private class ExtendThreadDemo extends Thread {
        //定一个循环数字
        private int a = 3;

        @Override
        public void run() {
            //线程名称
            String name = Thread.currentThread().getName();
            System.out.println(name + " 创建成功");
            while (a > 0) {
                a--;
                System.out.println("[ExtendThreadDemo]" + name + "我是数字:" + a);
            }
        }
    }

    //内部类继承实现Runnable创建线程
    private class RunnableThreadDemo implements Runnable {
        //定一个循环数字
        private int a = 3;

        @Override
        public void run() {
            //线程名称
            String name = Thread.currentThread().getName();
            System.out.println(name + " 创建成功");
            while (a > 0) {
                a--;
                System.out.println("[ExtendThreadDemo]" + name + "我是数字:" + a);
            }
        }
    }

    //使用extend创建线程测试
    public void extendThreadTest() {
        ExtendThreadDemo extendThreadDemo1 = new ExtendThreadDemo();
        ExtendThreadDemo extendThreadDemo2 = new ExtendThreadDemo();
        ExtendThreadDemo extendThreadDemo3 = new ExtendThreadDemo();
        extendThreadDemo1.start();
        extendThreadDemo2.start();
        extendThreadDemo3.start();
    }

    //使用implements创建线程测试
    public void runnableThreadTest() {
        RunnableThreadDemo runnableThreadDemo = new RunnableThreadDemo();
        Thread runnableThreadDemo1 = new Thread(runnableThreadDemo);
        Thread runnableThreadDemo2 = new Thread(runnableThreadDemo);
        Thread runnableThreadDemo3 = new Thread(runnableThreadDemo);
        runnableThreadDemo1.start();
        runnableThreadDemo2.start();
        runnableThreadDemo3.start();
    }

    //main方法测试
    public static void main(String[] args) {
        CreateThreadTest mainTest = new CreateThreadTest();
        mainTest.extendThreadTest();
//        mainTest.runnableThreadTest();
    }
}

当使用extendThreadTest进行测试的时候,打印日志如下:

Thread-0 创建成功
[ExtendThreadDemo]Thread-0我是数字:2
[ExtendThreadDemo]Thread-0我是数字:1
[ExtendThreadDemo]Thread-0我是数字:0
Thread-1 创建成功
[ExtendThreadDemo]Thread-1我是数字:2
[ExtendThreadDemo]Thread-1我是数字:1
[ExtendThreadDemo]Thread-1我是数字:0
Thread-2 创建成功
[ExtendThreadDemo]Thread-2我是数字:2
[ExtendThreadDemo]Thread-2我是数字:1
[ExtendThreadDemo]Thread-2我是数字:0

当使用runnableThreadTest进行测试的时候,打印日志如下:

Thread-0 创建成功
[ExtendThreadDemo]Thread-0我是数字:2
[ExtendThreadDemo]Thread-0我是数字:1
[ExtendThreadDemo]Thread-0我是数字:0
Thread-1 创建成功
Thread-2 创建成功

从以上结果我们可以看出,如果继承Thread的话里面的变量在每一个线程中都会各自复一份,但是如果使用Runable多个线程之间可以共享数据变量

关于线程的生命周期可以参考:JAVA线程的生命周期以及5种状态转换
https://blog.csdn.net/u011047968/article/details/106857781

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/72685.html

(0)
小半的头像小半

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!