Java实现多线程的两种方式比较及区别

Java实现多线程的两种方式比较及区别

    Java实现多线程的方式:2种

    方式1:自定义类继承Thread类
        1:自定义类MyThread继承Thread类
        2:MyThread类里面重写run()方法
        3:在测测试类MyThreadTest中创建MyThread类的对象
        4:启动线程

    方式2:自定义类实现Runnable接口
        1:自定义类MyRunnable实现Runnable接口
        2:MyRunnable类里面重写run()方法
        3:在测测试类MyRunnableTest中创建MyRunnable类的对象
        4;在测测试类MyRunnableTest中再创建Thread类的对象,并把3步骤的对象作为构造参数进行传递
        5:启动线程
        
    问题:
        1:为什么要重写run()方法?
            答:run()方法里面封装的是被线程执行的代码。
        2:启动线程对象用的是哪个方法?
            答:start()方法
        3:run()方法和start()方法的区别?
            答:run()方法直接调用仅仅是普通方法。
          start()方法是先启动线程,再由jvm去调用run()方法。
        4:有了方式1,为什么还来一个方式2呢?
            答:若自定义类MyThread类已经有一个父类了,那么它就不可以再去继承Thread类了。(java不支持多继承)
                若自定义类MyRunnable类已经实现了一个接口了,那么它还可以再去实现Runnable接口。(java支持多实现)
                即可以避免由于Java单继承带来的局限性。
                
                在测试类MyThreadTest中,要想开多个线程,就要先new多个自定义类MyThread的对象,每一个自定义类MyThread的对象的成员变量都相同,这样需要在栈中开辟很多内存;
                在测试类MyRunnableTest中,要想开多个线程,只需要new一个自定义类MyRunnable的对象,再new多个Thread类的对象即可,这样就大大节约了内存。
                即适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码和数据有效分离(即耦合性降低),较好的体现了Java面向对象的设计思想。

注意:图片中 1:为什么药重写run()方法?有个错别字药,应该为要。

示例代码如下:

方式1:自定义类继承Thread类

 1 package cn.itcast_02;
 2 
 3 /*
 4  * 该自定义的类为什么要重写run()方法?
 5  *         自定义类中不是所有的代码都需要被线程执行。
 6  *         而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()方法,用来包含那些需要被线程执行的代码。
 7  * 
 8  *         注意:这里的  被线程执行 = 开一个新线程执行
 9  */
10 public class MyThread extends Thread {
11     // 不需要被线程执行的代码
12     public void show() {
13         System.out.println("不需要被线程执行的代码"); // 这么简单的程序去开一个新的线程,纯属浪费啊!
14     }
15     
16     // 需要被线程执行的代码
17     @Override
18     public void run() {
19         // System.out.println("好好学习,天天向上"); // 这么简单的程序去开一个新的线程,纯属浪费啊!
20         
21         // 一般来说,被线程执行的代码肯定是比较耗时的。
22         // 所以这里示例:我们使用循环
23         for (int x = 0; x < 1000; x++) {
24             System.out.println(x);
25         }
26     }
27 
28 }
 1 package cn.itcast_02;
 2 
 3 /*
 4  * 需求:我们要实现多线程的程序。
 5  * 
 6  * 如何通过java程序来实现多线程的程序呢?
 7  *         由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来。
 8  *         而进程是由系统创建的,所以我们应该去调用系统功能创建一个进程。
 9  * 
10  *         而Java是不能直接调用系统功能的,所以,我们没有办法直接实现多线程程序。
11  *         但是呢?Java可以去调用C/C++写好的程序来间接实现多线程程序。
12  * 
13  *         由C/C++程序去调用系统功能去创建进程,然后由Java进行封装后,这样会产生一些类,我们通过这些类创建的对象去调用他们即可!
14  * 
15  *         这样我们就可以通过java程序来实现多线程程序了。
16  * 
17  * 那么Java提供的类是什么呢?
18  *         Thread类
19  *         通过查看API,我们知道了有2种方式可以实现多线程程序。
20  *         (其实有三种方法,第三种明天讲)
21  * 
22  * 实现多线程程序
23  * 方式1:继承Thread类
24  *         是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。之后就可以分配并启动该子类的实例了。
25  * 步骤
26  *         A:自定义类MyThread继承Thread类
27  *         B:MyThread类里面重写run()方法
28  *         C:在测测试类MyThreadTest中创建MyThread类的对象
29  *         D:启动线程
30  */
31 public class MyThreadTest {
32     public static void main(String[] args) {
33         // 在测测试类中创建自定义类的对象
34         // MyThread my = new MyThread();
35         // 启动线程
36         // my.run();
37         // my.run();
38         
39         // 调用run()方法为什么是单线程的呢?
40         // 因为run()方法直接调用其实就相当于普通的方法调用,所以你看到的是单线程的效果。
41         
42         // 要想看到多线程的效果,就必须说说另一个方法:start()
43         // 面试题:run()和start()的区别?
44         // run():仅仅是封装被线程执行的代码,直接调用就是普通方法。
45         // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。
46         
47         // MyThread my = new MyThread();
48         // my.start();
49         // my.start();
50         // IllegalThreadStateException:非法的线程状态异常
51         // 为什么呢?因为这个相当于是my线程被调用了两次。而不是两个线程被启动。一个线程不能被多次启动。
52 
53         // 创建两个线程对象
54         MyThread my1 = new MyThread();
55         MyThread my2 = new MyThread();
56         
57         my1.setName("林青霞");
58         my2.setName("刘意");
59 
60         my1.start();
61         my2.start();
62     }
63 }

方式2:自定义类实现Runnable接口

 1 package cn.itcast_05;
 2 
 3 public class MyRunnable implements Runnable {
 4 
 5     @Override
 6     public void run() {
 7         for (int x = 0; x < 100; x++) {
 8             // 由于自定义类实现了接口,所以就不能在自定义类中直接使用Thread类的getName()方法了,但是可以间接的使用。
 9             // 间接方法:Thread.currentThread().getName()
10             System.out.println(Thread.currentThread().getName() + ":" + x);
11         }
12     }
13 
14 }
 1 package cn.itcast_05;
 2 
 3 /* 
 4  * 实现多线程程序
 5  * 方式2:实现Runnable接口
 6  * 步骤:
 7  *         A:在自定义类MyRunnable实现Runnable接口
 8  *         B:MyRunnable类里面重写run()方法
 9  *         C:在测测试类MyRunnableTest中创建MyRunnable类的对象
10  *         D:在测测试类MyRunnableTest中再创建Thread类的对象,并把C步骤的对象作为构造参数进行传递
11  *         E:启动线程
12  */
13 public class MyRunnableTest {
14     public static void main(String[] args) {
15         // 在测测试类中创建MyRunnable类的对象
16         MyRunnable my = new MyRunnable();
17 
18         // public Thread(Runnable target)
19         // 在测测试类中再创建Thread类的对象,并把C步骤的对象作为构造参数进行传递
20         // Thread t1 = new Thread(my);
21         // Thread t2 = new Thread(my);
22         // t1.setName("林青霞");
23         // t2.setName("刘意");
24 
25         // Thread类的方法:
26         // public Thread(Runnable target, String name)
27         Thread t1 = new Thread(my, "林青霞");
28         Thread t2 = new Thread(my, "刘意");
29 
30         t1.start();
31         t2.start();
32     }
33 }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏python3

Python语句-if.....else......

似乎所有的条件语句都使用if.....else.....,它的作用可以简单地概括为非此即彼,满足条件A则执行A的语句,否则执行B语句,python的if.......

11120
来自专栏从零开始学 Web 前端

09 - JavaSE之线程

PS: 如果我们没有 new一个 Thread 对象出来,而是直接使用 MyThread 的 run 方法(mt.run()),这就是方法调用,而不是启动线程了...

15150
来自专栏二进制文集

Java多线程,循环打印“ABC”10次

3个线程A,B,C分别打印三个字母,每个线程循环10次,首先同步,如果不满足打印条件,则调用wait()函数一直等待;之后打印字母,更新state,调用noti...

40640
来自专栏Java编程技术

并发队列-无界非阻塞队列ConcurrentLinkedQueue原理探究

常用的并发队列有阻塞队列和非阻塞队列,前者使用锁实现,后者则使用CAS非阻塞算法实现,使用非阻塞队列一般性能比较好,下面就看看常用的非阻塞ConcurrentL...

16910
来自专栏mukekeheart的iOS之旅

Java基础——异常体系

在Java中,异常对象都是派生于Throwable类的一个实例,Java的异常体系如下图所示: ?    所有的异常都是由Throwable继承而来,在下一层立...

28670
来自专栏别先生

python的学习和使用

20300
来自专栏Java 源码分析

Java 虚拟机运行时数据区

运行时数据区: Java 虚拟机的运行时数据区按照大的可以分为线程独立使用的数据区,和所有线程共享的数据区。 一.线程独立使用数据区 1.程序计数器 程序计数器...

35440
来自专栏Java大联盟

Java面试手册:核心基础-3

2.数组有没有length()这个方法? String有没有length()这个方法?

21430
来自专栏yl 成长笔记

深刻理解反射(Reflection)

最近公司在搞自动化测试,由于版权问题,无法用 ’录制脚本‘ 进行,也就没法用 VS 自带的 UITest 框架(蛋疼), 所以只能开源的 FlaUI 框架来搞了...

16140
来自专栏云霄雨霁

设计模式----状态模式

16700

扫码关注云+社区

领取腾讯云代金券