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

网友投稿 211 2022-08-23


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 tiJizeMSVREIcket = 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 卖票--->3Thread-1 卖票--->2Thread-1 卖票--->1Thread-0 线程运行结束Thread-1 线程运行结束

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

public class RunnableDemo{

public static class RunnableTask implements Runnable{

// 数据资源

private int ticket = 3;

// 线程执行体

@Override

JizeMSVREI 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()方法

JizeMSVREIRunnable 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 卖票--->3thread1 卖票--->2thread1 卖票--->1thread1 线程运行结束thread2 线程运行结束

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

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

总结

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Python-Django 项目模块-年级模块开发(七)(pythondjango框架)
下一篇:python 中单元测试的应用(python代码大全)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~