【Java 并发编程】 01 多线程的实现

本文详细介绍了在Java中实现多线程的两种主要方法:继承Thread类和实现Runnable接口。对比了这两种方法的优缺点,包括代码结构、资源管理和线程控制等方面,推荐使用Runnable接口实现多线程。

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

常用的实现多线程的2种方式:继承 Thread 或者实现 Runanable 接口

Thread 类 实现了 Runnable 接口

public class Thread implements Runnable {}

//继承 Thread 类

public class MyThread extends Thread {
    /*
       static Thread currentThread(),返回正在执行的线程对象的引用
       public static void sleep(long millis) 当前正在执行的线程以指定毫秒数暂定(暂时停止执行),毫秒结束后继续执行

     */
    @Override
    public void run() {
        for (int i = 0; i <5 ; i++) {
            System.out.println(this.getName()+ "卖票"+i);
            //  使用Thread类中的方法 String getName(),可以返回线程的名称。
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class MainThread {
    public static void main(String[] args){
        // 启动3个线程t1,t2,t3;每个线程各循环5次!

        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        MyThread t3=new MyThread();
        t1.start();
        t2.start();
        t3.start();
    }

}

结果:
Thread-1卖票0
Thread-0卖票0
Thread-2卖票0
Thread-0卖票1
Thread-0卖票2
Thread-0卖票3
Thread-0卖票4
Thread-1卖票1
Thread-1卖票2
Thread-2卖票1
Thread-1卖票3
Thread-2卖票2
Thread-1卖票4
Thread-2卖票3
Thread-2卖票4

实现 Runnable 接口

Runnable接口中有一个抽象方法run
public interface Runnable { public abstract void run(); }

public class DemoRunnable implements  Runnable {
    @Override
    public void run() {
        for (int i = 0; i <5 ; i++) {
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}



public class MIanRunnable {
    public static void main(String[] args){
        //实例化DemoRunnable 对象
        DemoRunnable r=new DemoRunnable();
        //创建线程对象
        Thread t0=new Thread(r,"0号窗口");
        Thread t1=new Thread(r,"1号窗口");
        Thread t2=new Thread(r,"2号窗口");
        t0.start();
        t1.start();
        t2.start();

    }
}

结果:
1号窗口0
1号窗口1
2号窗口0
0号窗口0
0号窗口1
0号窗口2
0号窗口3
0号窗口4
2号窗口1
2号窗口2
2号窗口3
2号窗口4
1号窗口2
1号窗口3
1号窗口4

Thread 中的 start() 方法分析

是不是用一种疑问,逻辑业务在 run 方法中,为什么开启线程 要用start() 方法呢?

start() 源码如下所示:

public synchronized void start() {
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    group.add(this);

    boolean started = false;
    try {
        start0();
        started = true;
    } finally {
        try {
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
        }
    }
}
  • 检查线程的状态,是否可以启动;
  • 把线程加入到线程group中;
  • 调用了start0()方法。

Start方法中最终调用的是start0方法,并不是run方法,我们查看 start0() 方法,start0是一个native方法,也称为JNI(Java Native Interface)方法。JNI方法是java和其它语言交互的方式。同样也是java代码和虚拟机交互的方式,虚拟机就是由C++和汇编所编写。(一句话概括 ,native 修饰的方法 实在JVM 中的实现的,也就是说 start0() 方法 jvm 中,JVM 运行的 run() ) 👉 线程的生命周期
在这里插入图片描述

*the Java Virtual Machine calls the run method of this thread。
java虚拟机调用这个线程的run方法。*

private native void start0();

我们看一下run 方法,发现有一个target ,target 又是什么呢?

@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

查看 Thread 的构造函数,返现target 是一个Runnable的实现对象,

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

查看Thread 中 初始化方法,

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc,
                  boolean inheritThreadLocals){
   // target 为成员变量
  this.target = target;
}

在这里插入图片描述

Thread 和 Ruannable 区别

Thread,是一个类,实现是 Ruannable 接口。Ruannable 是一个接口。所以继承thread类实现多线程,其实也相当于是实现runnable接口的run方法。

java 是单继承语言,一个类只能有一个父类,但是可以实现多个接口,Ruannable的扩展性更加好一些,避免了java中单继承的局限性。

多个线程基于某一个Runnable对象建立的,共享Runnable对象资源,增加程序的健壮性,实现了解耦操作,代码和线程独立。

继承 Thread 类, run 方法实现在 Thread 子类中,thread 对象运行自己的 run 方法逻辑,创建对象以及业务逻辑没有分离,实现Runnable 接口,run方法逻辑转移到 Runnable 的实现类中,是调用 Runnable 实现的 run 方法逻辑,可以将创建对象和执行逻辑业务分离开来,线程控制逻辑在Thread类中,业务运行逻辑在Runnable实现类中。解耦更为彻底
在这里插入图片描述

通过以上比较,推荐使用 Ruannable 接口 实现多线程 。

出现这个错误的原因是在导入seaborn包时,无法从typing模块中导入名为'Protocol'的对象。 解决这个问题的方法有以下几种: 1. 检查你的Python版本是否符合seaborn包的要求,如果不符合,尝试更新Python版本。 2. 检查你的环境中是否安装了typing_extensions包,如果没有安装,可以使用以下命令安装:pip install typing_extensions。 3. 如果你使用的是Python 3.8版本以下的版本,你可以尝试使用typing_extensions包来代替typing模块来解决该问题。 4. 检查你的代码是否正确导入了seaborn包,并且没有其他导入错误。 5. 如果以上方法都无法解决问题,可以尝试在你的代码中使用其他的可替代包或者更新seaborn包的版本来解决该问题。 总结: 出现ImportError: cannot import name 'Protocol' from 'typing'错误的原因可能是由于Python版本不兼容、缺少typing_extensions包或者导入错误等原因造成的。可以根据具体情况尝试上述方法来解决该问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [ImportError: cannot import name ‘Literal‘ from ‘typing‘ (D:\Anaconda\envs\tensorflow\lib\typing....](https://blog.csdn.net/yuhaix/article/details/124528628)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值