[Java多线程]继承Thread类/实现Runnable接口

本文详细介绍了Java中实现多线程的两种方式:继承Thread类和实现Runnable接口。通过分析,强调了继承Thread类的单继承局限以及Runnable接口的优势。文章深入探讨了线程的启动过程,指出启动线程必须调用Thread的start()方法,并解释了start()方法的内部机制。此外,还讨论了线程与进程的关系以及在实际应用中的并发问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1进程与线程:

1.1进程:

1.2线程:

1.3两者关系:

2多线程的实现:

2.1继承Thread类(单继承局限)

总结:

2.2Runnable接口实现多线程

2.3继承Thread类与实现Runnable接口的关系:


1进程与线程:

1.1进程:

一个操作系统中一个程序的执行周期

1.2线程:

一个进程同时执行多个任务。通常来讲,每个任务就可以成称为一个线程

1.3两者关系:

1.线程更加的“轻量级”,创造和撤销一个线程比启动撤销一个进程的开销小的多

一个进程中所有线程共享此进程的所有资源

2.没有进程就没有线程,进程一旦终止,线程也将不复存在

3.进程是操作系统资源调度的基本单位,进程可以共享资源

线程需要依靠进程提供的资源,无法独立申请操作系统资源,是os任务执行的基本单位。

高并发:

指的是同一时刻访问的线程量特别高

2多线程的实现:

2.1继承Thread类(单继承局限)

java.lang.Thread是线程操作的核心类.新建一个线程最简单的方法就是继承Thread类.而后覆写run()方法(相当于主线程的main()方法)

//无论使用哪种方式实现线程,线程的启动一定调用Thread类提供的start()方法

//start源码:
public synchronized void start() {
    /**
    * This method is not invoked for the main method thread or "system"
    * group threads created/set up by the VM. Any new functionality added
    * to this method in the future may have to also be added to the VM.
    *
    * A zero status value corresponds to state "NEW".
    */
    if (threadStatus != 0)
      throw new IllegalThreadStateException();
    /* Notify the group that this thread is about to be started
    * so that it can be added to the group's list of threads
    * and the group's unstarted count can be decremented. */
    group.add(this);
    boolean started = false;//置为就绪态
    try {
 start0();
      started = true;
   } finally {
      try {
        if (!started) {
          group.threadStartFailed(this);
       }
     } catch (Throwable ignore) {
        /* do nothing. If start0 threw a Throwable then
         it will be passed up the call stack */
     }
   }
 }
  private native void start0();

由源码可知:

1线程的start()方法只能调用一次,多次调用会抛出IllegalThreadStateException(线程非法状态异常)

这个异常的产生只是因为你重复启动了线程才会产生。所以,每一个线程对象只能够启动一次

class MyThread extends  Thread{
    private String title;//MyTread的一个私有属性为title
    public MyThread(String title){
        this.title=title;
    }
    public void run(){
        for(int i=1;i<10;i++){
            System.out.println(this.title+"i="+i);
        }
    }
}
public class Thread1 {
    public static void main(String[] args) {
        MyThread thread=new MyThread("线程1");
        MyThread thread1=new MyThread("线程2");
        MyThread thread2=new MyThread("线程3");
        thread.run();
        thread1.run();
        thread2.run();
    }
}

native指的是调用本机的原生系统函数。
Thread 类有个 registerNatives 本地方法,

class Thread implements Runnable{
private static native void registerNatives(){
static {
registerNatives();
}
//其他属性
}

该方法主要的作用就是注册一些本地方法供 Thread 类使用,如start0(),stop0() 等等,

可以说,所有操作本地线程的本地方法都是由它注册的。


这个方法放在一个 static 语句块中,当该类被加载到 JVM 中的时候,它就会被调用,进而注册相应的本地方法

通俗点讲:就是把当前线程用到JVM的方法全都引进过来
而本地方法 registerNatives 是定义在 Thread.c 文件中的。Thread.c 是个很小的文件,它定义了各个操作系统平
台都要用到的关于线程的公用数据和操作,如下:

 JNIEXPORT void JNICALL
 Java_Java_lang_Thread_registerNatives (JNIEnv \*env, jclass cls){ //registerNatives
  (\*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
 }
 static JNINativeMethod methods[] = {
  {"start0", "()V",(void \*)&JVM_StartThread}, //start0 方法
  {"stop0", "(" OBJ ")V", (void \*)&JVM_StopThread},
  {"isAlive","()Z",(void \*)&JVM_IsThreadAlive},
  {"suspend0","()V",(void \*)&JVM_SuspendThread},
  {"resume0","()V",(void \*)&JVM_ResumeThread},
  {"setPriority0","(I)V",(void \*)&JVM_SetThreadPriority},
  {"yield", "()V",(void \*)&JVM_Yield},
  {"sleep","(J)V",(void \*)&JVM_Sleep},
  {"currentThread","()" THD,(void \*)&JVM_CurrentThread},
  {"countStackFrames","()I",(void \*)&JVM_CountStackFrames},
  {"interrupt0","()V",(void \*)&JVM_Interrupt},
  {"isInterrupted","(Z)Z",(void \*)&JVM_IsInterrupted},
  {"holdsLock","(" OBJ ")Z",(void \*)&JVM_HoldsLock},
  {"getThreads","()[" THD,(void \*)&JVM_GetAllThreads},
  {"dumpThreads","([" THD ")[[" STE, (void *)&JVM_DumpThreads},
};

总结:

先调用start()方法判断线程是否是新创建的

是新创建的---调用start0本地方法准备资源调度---jvm启动它----任务在run方法里面,所以回调run()方法

start(java方法)->start0()-进行资源调度系统分配(JVM)->到run(java方法)执行线程的具体操作

run()方法------用户自己调用的普通方法

start()方法-----JVM通过线程调用,赋予了run()方法进程

2.2Runnable接口实现多线程

该接口可以很好的解决单继承局限

接口Runnable源码:

@FunctionalInterface
public interface Runnable {
  /**
  * When an object implementing interface <code>Runnable</code> is used
  * to create a thread, starting the thread causes the object's
  * <code>run</code> method to be called in that separately executing
  * thread.
  * <p>
  * The general contract of the method <code>run</code> is that it may
  * take any action whatsoever.
  *
  * @see   java.lang.Thread#run()
  */
  public abstract void run();
}

@FunctionalInterface------检查当前接口中是否只有一个抽象方法

class MyThread implements Runnable{
    private String title;//MyTread的一个私有属性为title
    public MyThread(String title){
        this.title=title;
    }
    @Override
    public void run(){
        for(int i=1;i<10;i++){
            System.out.println(this.title+"i="+i);
        }
    }
}
public class Thread1 {//启动线程
    public static void main(String[] args) {
        MyThread thread=new MyThread("线程1");
        MyThread thread1=new MyThread("线程2");
        MyThread thread2=new MyThread("线程3");
        new Thread(thread).start();
        new Thread(thread1).start();
        new Thread(thread2).start();
    }
}

无论何种方式,启动线程,必须使用Thread类提供的start方法!

通过匿名内部类实现runnable 接口:

public class Thread1 {
    public static void main(String[] args) {
       Runnable runnable=new Runnable() {
           //匿名内部类
           @Override
           public void run() {
               System.out.println("Welcome to my world!");
           }
       };new Thread(runnable).start();
    }
}

2.3继承Thread类与实现Runnable接口的关系:

Thread类与自定义线程类(实现了Runnable接口是典型的代理设计模式)

  • Thread类----辅助真实业务操作(资源调度,创建线程并且启动)
  • 自定义线程类---真实业务的实现-----也就是run()方法具体要做什么事
  • Runnable接口实现的多线程程序类----可以更好的描述共享的概念

下面以卖票事件为例:

class MyThread{
    private int ticket=10;
    private String title;
    public MyThread(String  title){
        this.title=title;
    }
    public void run(){
        for(int i=0;i<10;i++){
            System.out.println(this.title+"还剩下:"+this.ticket+"张票");
        }
    }
}
public class Thread1 {
  public static void main(String[] args) {
        MyThread mt = new MyThread("黄牛");
        Thread thread1=new Thread(mt);
        Thread thraed2=new Thread(mt);
        thread1.start();
        thraed2.start();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值