Java(71):多线程学习02-->实现Runnable接口方式实现多线程

Java(71):多线程学习02-->实现Runnable接口方式实现多线程,第1张

Java(71):多线程学习02-->实现Runnable接口方式实现多线程

虽然Thread类可以实现多线程的主体类定义,但是它有一个问题,java具有单线程局限,正因如此针对于类的继承都应该是回避的问题,那么多线程也一样。为了解决单线程的限制,在java里面专门提供了Runnable接口。

1、实现Runnable接口方式实现多线程

与继承Thread类相比,实现Runnable接口的RunnableTest类在结构上与之前是没有区别的,但是有一点是有严重区别的,如果继承了Thread类,那么可以直接继承start()方法,但是实现Runnable接口是没有start()方法的。不管何种情况下,如果要启动多线程一定要依靠Thread类完成,多线程唯一的启动方法就是Thread类中的start方法。


如果自己的类已经extends另一个类,就无法直接extends Thread,此时,必须实现一个Runnable接口,

写一个类实现Runnable接口,实现run方法。用new Thread(Runnable target).start()方法来启动,如下:

 1.1定义Runnable接口的实现类
class RunnableTest  implements Runnable{
    private int ticket =10;
   //1.2重写其中的run方法
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if (this.ticket > 0) {
                System.out.println("票号:"+ticket-- + ",已被售卖,售卖窗口:" + Thread.currentThread().getName());
            }
        }
    }
}
1.1、线程独立完成任务

生成3个任务对象实例,每个任务生成独立的线程来执行:即3个卖票10张的任务分别分给3个窗口,他们各做各的事各卖各的票各完成各的任务。

RunnableTest rt1=new RunnableTest();
RunnableTest rt2=new RunnableTest();
RunnableTest rt3=new RunnableTest();
Thread t1 = new Thread(rt1,"1号窗口");
Thread t2 = new Thread(rt2,"2号窗口");
Thread t3 = new Thread(rt3,"3号窗口");
t1.start();
t2.start();
t3.start();

执行结果:

【线程的创建和启动的步骤(实现Runnable接口方式)】
1.定义Runnable接口的实现类,并重写其中的run方法。run()方法的方法体是线程执行体。
2.创建Runnable接口实现类的实例。                        RunnableTest rt1 = new RunnableTest();
3.用该实例作为Thread的target来创建Thread对象。   Thread t1=new Thread(rt1,"1号窗口");
4.调用该对象的start()方法启动线程。                       t1.start();

【关于命名】

在创建Thread 对象的时候可以为该Thread对象指定一个名字

Thread t1=new Thread(rt1,"1号窗口");

【Thread的构造方法】
Runnable对象作为Thread对象的target,Runnable实现类里面包含run方法仅仅作为执行体。也就是说Thread类的作用是把run方法包装成线程的执行体。
实际运行的线程对象依然是Thread实例,只是该Thread线程负责执行其target的run方法。

1.2、数据资源共享,一起完成

(再不考虑线程安全的情况下,学习的例子)

实际开发中我们通常采用Runnable接口来实现多线程。因为实现Runnable接口比继承Thread类有如下好处: 
1. 避免继承的局限,一个类可以继承多个接口,但是类只能继承一个类。 
2. Runnable接口实现的线程便于资源共享。而通过Thread类实现,各自线程(继承子类创建的对象线程)的资源是独立的,不方便共享。

public class RunnableDemo {
    public static void main(String[] args){
        //2.创建Runnable的接口实现类的实例
        RunnableTest rt1 = new RunnableTest();  
        //2.用Runnable的接口实现类的实例作为Thread的target,创建Thread对象,同时为之命名
        Thread t1=new Thread(rt1,"1号窗口");
        Thread t2=new Thread(rt1,"2号窗口");
        Thread t3=new Thread(rt1,"3号窗口");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

执行结果:

实现资源共享:

 编写一个任务类实现Runnable接口, 相当于是拿出一个卖票10张的任务给三个人去共同完成,new RunnableTest相当于创建一个任务,然后通过new Thread实例化3个Thread,创建3个线程即1个任务安排3个窗口去执行。

     实现Runable的一个好处就是能实现资源共享。当然实现一个任务用多个线程来做也可以用继承Thread类来实现只是比较麻烦,一般我们用实现Runnable接口来实现,简洁明了。
     大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应建议使用 Runnable 接口。

其他摘抄信息:

实现Runnable接口相对于继承Thread类来说,有如下显著的好处:
1.适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好地体现了面向对象的设计思想。
2.可以避免由于JAVA的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。
3.有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程可以 *** 作相同的数据,与它们的代码无关。当共享访问相同的对象时,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。
事实上,几乎所有多线程应用都可以用实现Runnable接口的方式。

-----------------------------

对于具有相同目标对象的线程,当其中一个线程享用CPU资源时,目标对象自动调用接口中的run()方法,这时run()方法中的局部变量被分配内存空间。当轮到另一个线程享用CPU资源时,目标对象会再次调用接口中的run()方法,那么run()方法中的局部变量会再次分配内存空间。也就是说,run()方法已经启动运行了两次,分别运行在不同的线程中,即运行在不同的时间片内。run()方法中的局部变量称为线程的局部变量。不同线程的run()方法中的局部变量互不干扰,一个线程改变了自己的run()方法中局部变量的值,不会影响其他线程的run()方法中的局部变量。

面试题:请解释Thread类和Runnable接口实现多线程的区别?(请解释多线程两种实现方式的区别?)

Thread类是Runnable接口的子类,使用Runnable接口实现多线程可以避免单继承局限。
Runnable接口实现的多线程可以比Thread类实现的多线程更加清楚的描述数据共享的概念。

参考:java学习线程篇之多线程的实现方式:继承Thread类、实现Runnable接口或Callable接口

https://blog.csdn.net/qq_34474324/article/details/100035644

参考:https://www.cnblogs.com/echo-cheng/p/6814909.html

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5573334.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-14
下一篇2022-12-14

发表评论

登录后才能评论

评论列表(0条)

    保存