Java中Runnable和Thread的区别
概述
Runnable 是接口。
Thread 是类,且实现了Runnable接口。
Thread部分源码
public class Thread implements Runnable { private static class Caches { static final ConcurrentMap subclassAudits = new ConcurrentHashMap(); static final ReferenceQueue subclassAuditsQueue = new ReferenceQueue();
在使用Runnable定义的子类中没有start()方法,只有Thread类中才有。
1 public interface Runnable 2 { 3 4 public abstract void run(); 5 }
Thread类,有一个构造方法:public Thread(Runnable targer)
1 public Thread(Runnable runnable) 2 { 3 daemon = false; 4 stillborn = false; 5 threadLocals = null; 6 inheritableThreadLocals = null; 7 threadStatus = 0; 8 blockerLock = new Object(); 9 init(null, runnable, (new StringBuilder()).append("Thread-").append(nextThreadNum()).toString(), 0L); 10 }
此构造方法接受Runnable的子类实例,也就是说可以通过Thread类来启动Runnable实现的多线程。
使用情况
在程序开发中只要是多线程肯定永远以实现Runnable接口为主。
实现Runnable接口相比继承Thread类有如下好处:
1、避免继承的局限,一个类可以继承多个接口。
2、适合于资源的共享。
实例
以卖票为例,总共只有10张动车票了,全国3个窗口在卖。
继承Thread类的方法
1 package multithreading; 2 3 public class MyThreadWithExtends extends Thread { 4 5 private int tickets = 10; 6 7 @Override 8 public void run() { 9 10 for (int i = 0; i <= 100; i++) { 11 if(tickets>0){ 12 System.out.println(Thread.currentThread().getName()+"--卖出票:" + tickets--); 13 } 14 } 15 } 16 17 18 public static void main(String[] args) { 19 MyThreadWithExtends thread1 = new MyThreadWithExtends(); 20 MyThreadWithExtends thread2 = new MyThreadWithExtends(); 21 MyThreadWithExtends thread3 = new MyThreadWithExtends(); 22 23 thread1.start(); 24 thread2.start(); 25 thread3.start(); 26 27 //每个线程都独立,不共享资源,每个线程都卖出了10张票,总共卖出了30张。如果真卖票,就有问题了。 28 } 29 30 }
运行结果:
Thread-0--卖出票:10
Thread-2--卖出票:10
Thread-1--卖出票:10
Thread-2--卖出票:9
Thread-0--卖出票:9
Thread-2--卖出票:8
Thread-1--卖出票:9
Thread-2--卖出票:7
Thread-0--卖出票:8
Thread-2--卖出票:6
Thread-2--卖出票:5
Thread-2--卖出票:4
Thread-1--卖出票:8
Thread-2--卖出票:3
Thread-0--卖出票:7
Thread-2--卖出票:2
Thread-2--卖出票:1
Thread-1--卖出票:7
Thread-0--卖出票:6
Thread-1--卖出票:6
Thread-0--卖出票:5
Thread-0--卖出票:4
Thread-1--卖出票:5
Thread-0--卖出票:3
Thread-1--卖出票:4
Thread-1--卖出票:3
Thread-1--卖出票:2
Thread-0--卖出票:2
Thread-1--卖出票:1
Thread-0--卖出票:1
每个线程都独立,不共享资源,每个线程都卖出了10张票,总共卖出了30张。如果真卖票,就有问题了。
实现Runnable接口方式
1 package multithreading; 2 3 public class MyThreadWithImplements implements Runnable { 4 5 private int tickets = 10; 6 7 @Override 8 public void run() { 9 10 for (int i = 0; i <= 100; i++) { 11 if(tickets>0){ 12 System.out.println(Thread.currentThread().getName()+"--卖出票:" + tickets--); 13 } 14 } 15 } 16 17 18 public static void main(String[] args) { 19 MyThreadWithImplements myRunnable = new MyThreadWithImplements(); 20 Thread thread1 = new Thread(myRunnable, "窗口一"); 21 Thread thread2 = new Thread(myRunnable, "窗口二"); 22 Thread thread3 = new Thread(myRunnable, "窗口三"); 23 24 thread1.start(); 25 thread2.start(); 26 thread3.start(); 27 } 28 29 }
运行结果:
窗口二--卖出票:10
窗口三--卖出票:9
窗口一--卖出票:8
窗口三--卖出票:6
窗口三--卖出票:4
窗口三--卖出票:3
窗口三--卖出票:2
窗口三--卖出票:1
窗口二--卖出票:7
窗口一--卖出票:5
每个线程共享了对象myRunnable的资源,卖出的总票数是对的,但是顺序是乱的,怎么办?
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了