Java Runnable和Thread实现多线程哪个更好你知道吗

目录
  • 1.避免由于Java单继承带来的局限性
  • 2.可以实现业务执行逻辑和数据资源的分离
  • 3.可以与线程池配合使用,从而管理线程的生命周期
  • 总结

实现Runnable 接口比继承Thread 类的方式更好:

(1)可以避免由于Java单继承带来的局限性;

(2)可以实现业务执行逻辑和数据资源的分离;

(3)可以与线程池配合使用,从而管理线程的生命周期;

1. 避免由于Java单继承带来的局限性

如果异步逻辑所在类已经继承了一个基类,就没有办法再继承Thread类。比如,当一个Dog类继承了Pet类,再要继承Thread类就不行了。所以在已经存在继承关系的情况下,只能使用实现Runnable接口的方式。

public class ThreadTask extends Thread {
    // 线程的执行体
    @Override
    public void run() {
        System.out.println("线程执行的任务");
    }
}
public class RunnableTask implements Runnable {
    // 线程的执行体
    @Override
    public void run() {
        System.out.println("线程执行的任务");
    }
}

2. 可以实现业务执行逻辑和数据资源的分离

逻辑和数据更好分离。通过实现Runnable接口的方法创建多线程更加适合同一个资源被多段业务逻辑并行处理的场景。在同一个资源被多个线程逻辑异步、并行处理的场景中,通过实现Runnable接口的方式设计多个target执行目标类可以更加方便、清晰地将执行逻辑和数据存储分离,更好地体现了面向对象的设计思想。

注意:并不是继承Thread类不能实现资源共享,而是没有实现Runnable接口更方便,更清晰,他们两的主要区别就是类和接口的区别,但是我们一般多用Runnable。

(1) 通过继承Thread类的方式实现多线程,数据资源和业务执行逻辑是耦合在一起的, 多个线程并发地完成各自的任务,访问各自的数据资源,而不是共享一份数据资源:

public class ThreadDemo extends Thread {
    // 数据资源
    private int ticket = 3;
    // 业务执行逻辑
    @Override
    public void run() {
        for(int i=0;i<3;i++){
            if(ticket>0){
                System.out.println(Thread.currentThread().getName()+" 卖票--->"+ ticket--);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(Thread.currentThread().getName()+" 线程运行结束");
    }
    public static void main(String[] args) throws InterruptedException {
        // 创建2个线程,分别去执行线程体中的业务逻辑
        Thread thread1 = new ThreadDemo();
        thread1.start();
        Thread thread2 = new ThreadDemo();
        thread2.start();
        Thread.sleep(1000);
        System.out.println("main线程运行结束");
    }
}

多个线程并发地完成各自的任务,访问各自的数据资源:

Thread-0 卖票--->3
Thread-1 卖票--->3
main线程运行结束
Thread-0 卖票--->2
Thread-1 卖票--->2
Thread-1 卖票--->1
Thread-0 卖票--->1
Thread-0 线程运行结束
Thread-1 线程运行结束

(2) 通过继承Thread类可以实现资源共享:

public class ThreadTask {
    private int ticket = 3;
    public synchronized void saleTicket(){
        for(int i=0;i<3;i++){
            if(ticket>0){
                System.out.println(Thread.currentThread().getName()+" 卖票--->"+ticket--);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(Thread.currentThread().getName()+" 线程运行结束");
    }
}
public class ThreadA extends Thread {
    ThreadTask threadTask ;
    public ThreadA(ThreadTask threadTask){
        super();
        this.threadTask = threadTask;
    }
    @Override
    public void run() {
        threadTask.saleTicket();
    }
}
public class ThreadB extends Thread {
    ThreadTask threadTask ;
    public ThreadB(ThreadTask threadTask){
        super();
        this.threadTask = threadTask;
    }
    @Override
    public void run() {
        threadTask.saleTicket();
    }
}
public class Main {
    public static void main(String[] args) throws InterruptedException {
        ThreadTask threadTask = new ThreadTask();
        ThreadA t1 = new ThreadA(threadTask);
        ThreadB t2 = new ThreadB(threadTask);
        t1.start();
        t2.start();
    }
}

执行结果:

Thread-0 卖票--->3
Thread-1 卖票--->2
Thread-1 卖票--->1
Thread-0 线程运行结束
Thread-1 线程运行结束

(3) 通过实现Runnable接口实现多线程,能更好地做到多个线程并发地完成同一个任务,访问同一份数据资源。多个线程的代码逻辑可以方便地访问和处理同一个共享数据资源 ,这样可以将线程逻辑和业务数据进行有效的分离,更好地体现了面向对象的设计思想。

public class RunnableDemo{
    public static class RunnableTask  implements Runnable{
        // 数据资源
        private int ticket = 3;
        // 线程执行体
        @Override
        public synchronized void run() {
            for(int i=0;i<3;i++){
                if(ticket>0){
                    System.out.println(Thread.currentThread().getName()+" 卖票--->"+ticket--);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            System.out.println(Thread.currentThread().getName()+" 线程运行结束");
        }
    }
    public static void main(String[] args) {
        // 将这一个target作为参数传给两个线程,那么这两个线程执行的都是这个target的run()方法
        Runnable target = new RunnableTask();
        // 创建两个线程执行target的线程体
        Thread thread1 = new Thread(target,"thread1");
        thread1.start();
        Thread thread2 = new Thread(target,"thread2");
        thread2.start();
        System.out.println("main线程运行结束");
    }
}

多个线程并发地完成同一个任务,访问同一份数据资源:

main线程运行结束
thread1 卖票--->3
thread1 卖票--->2
thread1 卖票--->1
thread1 线程运行结束
thread2 线程运行结束

3. 可以与线程池配合使用,从而管理线程的生命周期

实现Runnable接口来实现线程,执行目标类,更容易和线程池配合使用,异步执行任务在大多数情况下是通过线程池去提交的,而很少通过创建一个新的线程去提交,所以更多的做法是,通过实现Runnable接口创建异步执行任务,而不是继承Thread去创建异步执行任务。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • java 多线程Thread与runnable的区别

    java 多线程Thread与runnable的区别 java中实现多线程的方法有两种:继承Thread类和实现runnable接口 1,继承Thread类,重写父类run()方法 public class thread1 extends Thread { public void run() { for (int i = 0; i < 10000; i++) { System.out.println("我是线程"+this.getId()); } } public static

  • java实现多线程的两种方式继承Thread类和实现Runnable接口的方法

    实现方式和继承方式有什么区别呢? *区别: *继承Thread:线程代码存放在Thread子类run方法中 *实现Runnable:线程代码存放在接口的子类的run方法中 *实现方式的好处:避免了单继承的局限性 *在定义线程时,建议使用实现方式,当然如果一个类没有继承父类,那么也可以通过继承Thread类来实现多线程 *注意:Runnable接口没有抛出异常,那么实现它的类只能是try-catch不能throws *Java对多线程的安全问题提供了专业的解决方式就是同步代码块synchroniz

  • JAVA多线程Thread和Runnable的实现

    java中只允许单一继承,但允许实现多个接口,因此第二种方法更灵活. 复制代码 代码如下: /**     * 运行继承java.lang.Thread类定义的线程     */    public void startOne() {        // 创建实例        OneThread oneThread = new OneThread();        // 启动线程ThreadA        oneThread.startThreadA();        try {    

  • Java Runnable和Thread实现多线程哪个更好你知道吗

    目录 1.避免由于Java单继承带来的局限性 2.可以实现业务执行逻辑和数据资源的分离 3.可以与线程池配合使用,从而管理线程的生命周期 总结 实现Runnable 接口比继承Thread 类的方式更好: (1)可以避免由于Java单继承带来的局限性: (2)可以实现业务执行逻辑和数据资源的分离: (3)可以与线程池配合使用,从而管理线程的生命周期: 1. 避免由于Java单继承带来的局限性 如果异步逻辑所在类已经继承了一个基类,就没有办法再继承Thread类.比如,当一个Dog类继承了Pet类

  • Android开发笔记之:Handler Runnable与Thread的区别详解

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限.下面看例子: 复制代码 代码如下: package org.thread.demo; class MyThread extends Thread{ private String name; public MyThread(St

  • Java中使用Thread类和Runnable接口实现多线程的区别

    使用Thread类和Runnable接口实现多线程的区别 先看两种实现方式的步骤: public class ThreadDemo{ public static void main(String[] args) { for (int i = 0; i < 5; i++) { //创建并启动由继承Thread类创建的线程 new Thread(new MyThread(),"Thread"+i).start(); //创建并启动由实现Runnable接口创建的线程 new Thre

  • 浅析Java中Runnable和Thread的区别

    线程的起动并不是简单的调用了你的RUN方法,而是由一个线程调度器来分别调用你的所有线程的RUN方法, 我们普通的RUN方法如果没有执行完是不会返回的,也就是会一直执行下去,这样RUN方法下面的方法就不可能会执行了,可是线程里的RUN方法却不一样,它只有一定的CPU时间,执行过后就给别的线程了,这样反复的把CPU的时间切来切去,因为切换的速度很快,所以我们就感觉是很多线程在同时运行一样. 你简单的调用run方法是没有这样效果的,所以你必须调用Thread类的start方法来启动你的线程.所以你启动

  • Java使用Runnable和Callable实现多线程的区别详解

    使用Runnable和Callable接口实现多线程的区别 先看两种实现方式的步骤: 1.实现Runnable接口 public class ThreadDemo{ public static void main(String[] args) { for (int i = 1; i <= 5; i++) { //创建并启动由实现Runnable接口创建的线程 new Thread(new Runner(),"Thread"+i).start(); } } } //实现Runnab

  • Java使用Thread创建多线程并启动操作示例

    本文实例讲述了Java使用Thread创建多线程并启动操作.分享给大家供大家参考,具体如下: 按照教程实现了一个单线程的创建,但是单线程的创建于启动并不是很有实用价值的.毕竟直接在main方法中放着相关的执行操作本身也就是一种单线程的实现.接下来在之前用过的代码基础上稍作修改,形成如下代码: class ThreadDemo extends Thread { ThreadDemo(){}; ThreadDemo(String szName) { super(szName); } public v

  • Java利用future及时获取多线程运行结果

    Future接口是Java标准API的一部分,在java.util.concurrent包中.Future接口是Java线程Future模式的实现,可以来进行异步计算. 有了Future就可以进行三段式的编程了,1.启动多线程任务2.处理其他事3.收集多线程任务结果.从而实现了非阻塞的任务调用.在途中遇到一个问题,那就是虽然能异步获取结果,但是Future的结果需要通过isdone来判断是否有结果,或者使用get()函数来阻塞式获取执行结果.这样就不能实时跟踪其他线程的结果状态了,所以直接使用g

  • Java常见面试题之多线程和高并发详解

    volatile 对 volatile的理解 volatile 是一种轻量级的同步机制. 保证数据可见性 不保证原子性 禁止指令重排序 JMM JMM(Java 内存模型)是一种抽象的概念,描述了一组规则或规范,定义了程序中各个变量的访问方式. JVM运行程序的实体是线程,每个线程创建时 JVM 都会为其创建一个工作内存,是线程的私有数据区域.JMM中规定所有变量都存储在主内存,主内存是共享内存.线程对变量的操作在工作内存中进行,首先将变量从主内存拷贝到工作内存,操作完成后写会主内存.不同线程间

  • Java学习随记之多线程编程

    Process和Thread 程序是指令和数据的有序集合, 本身没有运行的含义,是一个静态的概念. 进程是执行程序的一次执行过程,他是一个动态的概念,是系统资源分配的单位 一个进程中可以包含若干个线程,线程是CPU调度和执行的单位 线程创建 三种创建方法 继承Thread类 //创建线程方法一:继承Thread类,重写run() 方法,调用start开启主线程 public class TestThread01 extends Thread{ @Override public void run(

  • Java commons io包实现多线程同步图片下载入门教程

    目的: 实现多线程同时下载网络图片,入门级. 多线程入门 commons io: 是针对开发IO流功能的工具类库,其中包含了许多可调用的函数. 1.commons io 可直接百度,进入官网直接下载即可 Linux下载tar.gz,window下载.zip. 2.解压commons io ,复制下面的java文件,后在项目中,新建package,我的名为lib,如下,将复制的java文件粘贴到package中,并鼠标右击此文件,点击add as a library即可. 3.代码如下:多线程基础

随机推荐