多线程详细讲解

本文介绍了多线程的基本概念,包括程序、进程与线程的区别,并行与并发的概念;详细讲解了Java中多线程的创建与启动方法,包括通过继承Thread类和实现Runnable接口两种方式;还介绍了线程的生命周期及常用方法。

一.基本概念

1.程序

        一段静态代码

2.进程

        一段正在运行的程序,如360安全卫士

3.线程

        一段程序内部的执行路径,多线程就是指一个进程中有多个线程,如打开360安全卫士后可以同时开展木马查杀与垃圾清理连个线程

        每个线程拥有独立的运行栈和程序计数器,与其他线程共享进程中的

4.单核CPU与多核CPU

        单核CPU是一种假的多线程,看似同时执行多个线程,实则每个单元时间(很短)只执行一个线程

        多核CPU可以更好发挥多线程效率

5.并行与并发

        并行是指,多个CPU同时执行多个任务,比如多个人做不同的事

        并发是值,一个CPU(采用时间片切换)同时执行多个任务,如秒杀,多个人做一件事

二.多线程的创建与启动

一.创建一个继承自Thread类的子类(方式一)

1.重写run()方法

2.创建Thread子类的对象

3.调用start()方法

public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();//创建对象
        myThread.start();
        for(int i = 0;i<10000;i++){
            System.out.print("&&"+" ");
        }

    }
}
class MyThread extends Thread{//继承自Thread的子类
    @Override
    public void run() {//重写run()方法
        for(int i = 0;i<10000;i++){
            System.out.print(i+" ");
        }
    }
}

注意:

I.如果对象直接调用run()方法,只会体现类调用方法,而不会是创建新线程

II.对象执行过一次start()方法后不可以再让该对象调用start()方法

III.主线程main与自定义线程没有优先级之分,上述代码运行后会看到明显的交互现象

二.线程常用方法

1.void start():

        启动线程,并执行对象的run()方法

2.void run():

        线程在被调度时执行的操作

3.String getName():

        返回线程的名称

4.void setName():

        设置当前线程的名称

5.static Thread currentThread():

        返回当前线程,在Thread子类中就是this,通常用于main与Runable类

6.static void yleId():

        线程让步,暂停正在执行的该线程,把执行机会让给优先级相同或更高的线程,若没有则忽略此方法

7.join():

        当前程序执行时调用其他线程join方法,会使当前线程阻塞,知道join()方法加入的join线程被执行完为止

三.线程优先级设置

1.线程优先级常量

        I.MAX_PRIORITY:10

        II.MIN_PRIORITY:1

        III.NORM_PRIORITY:5

2.涉及方法

        getPriority():返回线程的优先级

        setPriority(int newPriority):改变线程的优先级

3.注意事项

        线程创建时继承父类的优先级

        低优先级只是获得调度的概率低,而不是一定在高优先级线程之后才会被调用

四.继承Runnable接口(方式二)

public class Main2 {
    public static void main(String[] args) {
        //3.创建实现类对象
        myThread2 m = new myThread2();
        //4.将此对象作为参数,传到Thread对象构造器中
        Thread t1 = new Thread(m);
        //5.调用start()方法
        t1.start();
    }
}
class myThread2 implements Runnable{//1.新建类实现Runnable接口

    //2.实现Runnable接口中的抽象run()方法
    @Override
    public void run() {
        for(int i = 0;i<100;i+=2)
            System.out.println(i);
    }
}

五.两种方式比较与选择

优先选择方式二:实现Runnable接口

1.没有单继承性的局限性

2.可实现数据共享

三.线程的生命周期

1.新建

        当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态

2.就绪:

        处于新建状态状态的线程被start()后,将进入线程的队列等待CPU时间片,此时它已经具备了运行的条件,只是没分配到CPU资源

3.运行

        当就绪的线程被调度并获得CPU资源时,便进入运行状态,run()方法定义了线程的操作和功能

4.阻塞

        在某种特定的情况下,被人为挂起或执行输入输出操作时,让出CPU并临时中止自己的执行,进入阻塞状态

5.死亡:

        线程完成了它全部工作或提前出线异常导致结束

<think>我们正在回答用户关于Python多线程详细讲解的问题。根据用户提供的引用内容,我们需要整合这些信息,并按照系统指令的要求进行回答。 引用[1]提到Python多线程用于提高程序运行效率,但作者后来意识到Python多线程机制的一些内情(暗示可能有一些限制或误解)。 引用[2]给出了一个多线程的示例代码,展示了如何使用threading模块创建线程、启动线程以及使用join()和setDaemon()方法。 引用[3]解释了多线程的概念,即在主线程中运行多个子线程,它们属于同一个进程,并提到了主线程与子线程的关系。 结合这些引用,我们可以给出以下讲解: 1. Python多线程的基本概念:使用threading模块,可以创建多个线程(子线程)在同一个进程中运行,主线程负责执行主程序。 2. 线程的创建:通过创建threading.Thread对象,指定目标函数和参数。 3. 线程的启动:调用start()方法启动线程。 4. 线程的同步:使用join()方法可以让主线程等待子线程完成。 5. 守护线程:通过setDaemon(True)将子线程设置为守护线程,当主线程结束时,守护线程也会随之结束。 另外,需要特别注意的是,由于GIL(全局解释器锁)的存在,Python的多线程并不适合计算密集型的任务,因为同一时刻只有一个线程在执行Python字节码。但对于I/O密集型任务,多线程仍然可以提高效率。 下面我们将按照用户要求,给出一个详细讲解,包括示例代码(按照用户提供的引用[2]中的代码,但会做适当调整和注释)以及相关概念的说明。 注意:在回答中,我们将使用中文,并确保行内公式(如果有的话)用$...$,独立公式用$$...$$(尽管多线程讲解可能较少涉及数学公式,但如果有必要我们会遵循)。同时,在回答末尾生成相关问题。 由于用户要求生成相关问题,我们将在最后生成几个相关问题。 现在开始编写回答: </think>### Python多线程详细讲解 Python的多线程通过`threading`模块实现,它允许在单个进程中并发执行多个线程。但由于GIL(全局解释器锁)的限制,Python多线程**更适用于I/O密集型任务**(如网络请求、文件读写),而非CPU密集型任务(如数值计算)。以下是核心概念和用法详解: --- #### **1. 基本使用** ```python import threading import time def task(name, delay): print(f"{name}开始执行: {time.ctime()}") time.sleep(delay) # 模拟I/O操作 print(f"{name}结束执行: {time.ctime()}") # 创建线程 t1 = threading.Thread(target=task, args=("线程1", 2)) t2 = threading.Thread(target=task, args=("线程2", 3)) # 启动线程 t1.start() t2.start() # 等待线程结束 t1.join() t2.join() print(f"主线程结束: {time.ctime()}") ``` - **`Thread()`参数**: - `target`:线程执行的函数(函数名,不加括号) - `args`:函数参数的元组形式 - **`start()`**:启动线程 - **`join()`**:阻塞主线程,直到子线程完成[^2] --- #### **2. 守护线程(Daemon Thread)** ```python t = threading.Thread(target=task, args=("守护线程", 5)) t.setDaemon(True) # 设置为守护线程 t.start() print("主线程直接结束,不等待守护线程") ``` - 守护线程会随主线程结束而强制终止 - 适用于后台任务(如日志监控),无需等待其完成[^2] --- #### **3. 线程同步与锁机制** 当多个线程修改共享数据时,需使用锁避免竞争: ```python counter = 0 lock = threading.Lock() def increment(): global counter with lock: # 自动获取和释放锁 for _ in range(100000): counter += 1 threads = [] for _ in range(5): t = threading.Thread(target=increment) threads.append(t) t.start() for t in threads: t.join() print(counter) # 正确输出500000 ``` - **`Lock()`**:确保同一时刻只有一个线程访问共享资源 - **`with lock`**:上下文管理器自动处理锁的获取/释放 --- #### **4. GIL(全局解释器锁)的局限性** - **GIL本质**:Python解释器一次只允许一个线程执行Python字节码 - **影响**: - 多线程无法利用多核CPU进行并行计算 - CPU密集型任务使用多进程(`multiprocessing`)更高效 - **适用场景**: - I/O密集型:多线程可显著提升效率(线程在I/O等待时释放GIL) - CPU密集型:需改用多进程[^1][^3] --- #### **5. 线程通信:队列(Queue)** ```python from queue import Queue def producer(q): for i in range(5): q.put(i) print(f"生产: {i}") def consumer(q): while True: item = q.get() if item is None: # 终止信号 break print(f"消费: {item}") q = Queue() t1 = threading.Thread(target=producer, args=(q,)) t2 = threading.Thread(target=consumer, args=(q,)) t1.start() t2.start() t1.join() q.put(None) # 发送终止信号 t2.join() ``` - **线程安全队列**:`Queue`提供阻塞操作(`put()`/`get()`) - 避免手动锁管理,简化生产者-消费者模式 --- ### **关键注意事项** 1. **线程间共享内存**:所有线程可直接访问主线程的全局变量 2. **避免死锁**:按固定顺序获取多个锁 3. **线程局部数据**:用`threading.local()`创建线程私有变量 4. **替代方案**:CPU密集型任务优先考虑`multiprocessing`或`concurrent.futures`模块 > Python的多线程机制在I/O操作中能有效提升效率,但需理解GIL的影响以规避性能陷阱[^1][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值