黑马程序员_多线程

发布时间:2024年01月17日

基础知识

  • 什么是线程
    • 被包含在进程之中, 可以调度的最小单位
    • 应用软件中互相独立,可以同时运行的功能
  • 什么是进程
    • 程序的基本执行实体

总结:

  • 什么是多线程?
    • 有了多线程,可以让程序同时做多件事情
  • 多线程有什么作用?
    • 提供程序的运行效率

  • 并发是什么?
    • 在同一时刻,有多个指令在单个 CPU 上交替执行
  • 并行是什么
    • 在同一时刻,有多个指令在单个 CPU 上同时执行

image.png

在线程中进行并发和并行

多线程的实现方式

第一种继承 Thread 类方式实现:

  1. 定义一个类继承 Thread
  2. 重写 run 方法
  3. 创建对象实例

image.png

image.png

以 Runnable 接口的方式实现

  1. 实现Runnable 接口
  2. 重写方法
  3. 创建实例
  4. 将实例放入 Thread 类对象中

image.png

image.png

Callable接口

有返回值,可以获得多线程的结果

特点:

  1. 创建一个类实现Callable接口
  2. 重写call方法
  3. 创建实例对象
  4. 创建FutureTask对象管理线程结果
  5. 创建Thread类对象 获取结果

image.png

image.png

常见的成员方法

image.png

演示方法:

getName()和setName()

返回线程的名字:
image.png

public class Mythread_01 extends Thread{  
    @Override  
    public void run() {  
        for (int i = 0; i < 100; i++) {  
            System.out.println(getName() + "@" + i);  
        }  
    }  
}

返回的默认名字格式为Thread-序号

  1. 使用setname
  2. 使用Thread(String name)
    1. 但是需要在继承类中使用super方法把带有String的构造方法写出来

线程的优先级

抢占式调度特点:随机

//使用setPriority来设置优先级
t1.setPriority(1);  
t2.setPriority(10);  
t2.start();  
t1.start();

守护线程

当其他非守护线程执行完毕,守护线程会陆续结束

当主线程结束,守护线程是跟着结束

插入线程

image.png

线程.join()

可以讲线程提前用完

线程的生命周期

image.png

线程安全问题

  • 当线程被共享后,其中的数据也会被其他线程修改导致不安全
    • 解决方式:把共享的数据锁起来
      synchronized 锁的特点:
  1. 锁默认打开,有线程进去自动关闭
  2. 代码全部执行完毕,锁自动打开
    image.png
    锁(类的字节码->唯一对象)

同步方法

image.png

image.png

lock锁

image.png
标准写法:

Lock lock = new ReentrantLock();

while(true){  
  //  synchronized (Myrunnable.class){  
    lock.lock();  
    try {  
        if(ticket == 100){  
            break;  
        }else{  
            Thread.sleep(10);  
            ticket++;  
            System.out.println(Thread.currentThread().getName() + " sell " + ticket + " tickets");  
        }  
    } catch (Exception e) {  
        throw new RuntimeException(e);  
    } finally {  
        lock.unlock();  
    }

死锁

死锁是一种错误,需要我们去避免的
特点:

  • A锁等着拿B锁
  • B锁等着拿A锁
  • 互相卡死
    image.png

生产者和消费者

完整过程:
image.png

常见方法

image.png
代码执行的流程:

  1. 循环
  2. 同步代码块
  3. 判断共享数据是否到了末尾(到了末尾)
  4. 判断共享数据是否到了末尾(未到末尾)

分为三块代码:
Desk:控制消费者和生产者的行为

package 生产者消费者;  
  
public class Desk {  
  
  
    //Desk:控制生产者和消费者的行为  
  
    // 是否有面条  
    public static int foodFlag = 0;  
  
    //制造的个数  
    public static int count = 10;  
  
    //锁对象  
    public static Object lock = new Object();  
}

Cook:生产者

package 生产者消费者;  
  
public class Cook extends Thread {  
    @Override  
    public void run() {  
        while (true) {  
            synchronized (Desk.lock) {  
                if (Desk.count == 0) { //桌子上的食物做够了  
                    break;  
                }else{  
                    //判断是否有食物  
                    if(Desk.foodFlag == 1){ //如果有食物 等待消费者来吃  
                        try {  
                            Desk.lock.wait();  
                        } catch (InterruptedException e) {  
                            throw new RuntimeException(e);  
                        }  
                    }else{  
                        //如果没有食物 做  
                        //修改食物状态  
                        System.out.println("厨师做了一碗面条");  
                        Desk.foodFlag = 1;  
                        //叫醒消费者吃  
                        Desk.lock.notifyAll();  
                    }  
                }  
            }  
        }  
    }  
}

Foodie:消费者

package 生产者消费者;  
public class Foodie extends Thread{  
    @Override  
    public void run() {  
        while(true){  
            synchronized (Desk.lock){  
                if(Desk.count == 0){ //桌子上的食物做够了  
                    break;  
                }else {  
                    //判断桌子上有没有面条  
                    if(Desk.foodFlag ==  0){  
                        //如果没有 就等待  
                        try {  
                            Desk.lock.wait(); //让线程等待  
                        } catch (InterruptedException e) {  
                            throw new RuntimeException(e);  
                        }  
                    }else{ //如果有 直接开吃  
                        Desk.count--;  
                        System.out.println("吃货吃了一碗,还剩" + Desk.count + "碗!");  
                        //唤醒厨师! 份数-1  
                        Desk.lock.notifyAll();  
                        //修改桌子的状态  
                        Desk.foodFlag = 0;  
                    }  
                }  
            }  
        }  
    }  
}

阻塞队列方式

image.png
实现类:
ArrayBlockingQueue
LinkedBlockingQueue

队列和链表自带锁

线程的状态

七大状态:
image.png

线程中的栈

image.png

当在run方法中创建了一个集合,那么每一个线程都会维持一个创建的集合(类似于static)

线程池

image.png

image.png

image.png

代码:
image.png

自定义线程池

image.png
image.png

最大并行数

  • 什么是最大并行数?
    就是电脑的核心处理单元和线程,这里是八核十六线程
    image.png

image.png

计算类型多:

image.png
读取文件或者数据库比较多:
image.png

文章来源:https://blog.csdn.net/weixin_51429898/article/details/135641738
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。