多线程知识点总结(通俗易懂)

1. 进程与线程的区别

进程:进程是程序执行时的一个实例,程序运行时系统就会创建一个进程,并为它分配资源,是CPU、内存等分配的基本单位。

线程:线程是进程的一条执行路径,是程序运行时的最小单位,线程间共享进程的资源,一个进程可以由多个线程组成,每个线程都有自己的堆栈和局部变量。

一个正在运行的软件(如迅雷)就是一个进程,一个进程可以同时运行多个任务( 迅雷软件可以同时下载多个文件,每个下载任务就是一个线程), 可以简单的认为进程是线程的集合。

2.并行与并发的区别

并行:多个CPU处理器同时处理多个线程任务,就比如多个食堂阿姨分别给自己窗口对应的队列打饭,互不影响。

并发:一个CPU处理器同时处理多个线程任务,轮流处理线程。例如,一个食堂阿姨给不同的队列轮流打饭,不同队列的人会去抢占打饭窗口。
并发可以在一个或多个CPU处理器系统中都存在,并行在多个CPU处理器系统存在。

3. 多线程实现方式

3.1 继承Thread类

package com.beantechs.demo.javaBase.thread;

import java.util.Date;
import java.util.concurrent.Callable;

/**
 * @author ymy
 */
public class ThreadDemo001 {
    public static void main(String[] args) throws InterruptedException {
        EatFood cookFood = new EatFood();
        cookFood.start();
        DrinkBeer playGame = new DrinkBeer();
        playGame.start();
    }
}

class EatFood extends Thread {
    @Override
    public void run() {
        System.out.println("吃烧烤:"+ new Date());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("烧烤吃完了:"+new Date());
    }
}

class DrinkBeer extends Thread {
    @Override
    public void run() {
        System.out.println("喝啤酒:"+new Date());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("喝酒结束:"+new Date());
    }
}

两个线程运行时间是相同的,两个线程并发执行:

吃烧烤:Fri Dec 29 14:15:59 CST 2023
喝啤酒:Fri Dec 29 14:15:59 CST 2023
烧烤吃完了:Fri Dec 29 14:16:04 CST 2023
喝酒结束:Fri Dec 29 14:16:04 CST 2023

3.2 实现Runnable:重写run()方法,然后使用Thread类来包装

package com.beantechs.demo.javaBase.thread;

/**
 * @author ce03904ym
 */
public class RunnableDemo {
    public static void main(String[] args) {
        RunDemo runDemo = new RunDemo();
        new Thread(runDemo).start();
    }
}
class RunDemo implements Runnable{
    @Override
    public void run() {
        System.out.println("去钓鱼");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("钓鱼结束,回家");
    }
}

3.3 Callable:重写call()方法,然后包装成java.util.concurrent.FutureTask, 再然后包装成Thread

package com.beantechs.demo.javaBase.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class CallableDemo {
    public static void main(String[] args) {
        CallDemo callDemo = new CallDemo();
        FutureTask futureTask = new FutureTask<>(callDemo);
        new Thread(futureTask).start();
    }
}
class CallDemo implements Callable {

    @Override
    public Object call() throws Exception {
        System.out.println("去游泳");
        return null;
    }
}

4.线程的状态

  1. 创建(new)状态: 准备好了一个多线程的对象,即执行了new Thread(); 创建完成后就需要为线程分配内存
  2. 就绪(runnable)状态: 调用了start()方法, 等待CPU进行调度
  3. 运行(running)状态: 执行run()方法
  4. 阻塞(blocked)状态: 暂时停止执行线程,将线程挂起(sleep()、wait()、join()、没有获取到锁都会使线程阻塞), 可能将资 源交给其它线程使用
  5. 死亡(terminated)状态: 线程销毁(正常执行完毕、发生异常或者被打断interrupt()都会导致线程终止)
    在这里插入图片描述

5. start() 与 run()方法的区别

start(): 启动一个线程,线程之间是没有顺序的,是按CPU分配的时间片来回切换的。

run(): 调用线程的run方法,就是普通的方法调用,run()方法用于封装线程的代码,具体要启动一个线程来运行线程体中的代码(run()方法)还是通过start()方法来实现,调用run()方法就是一种顺序编程不是并发编程。

6. sleep() 与wait() 方法介绍

sleep(long millis): 睡眠指定时间,程序暂停运行,睡眠期间会让出CPU的执行权,去执行其它线程,同时CPU也会监视睡眠的时间,一旦睡眠时间到就会立刻执行(因为睡眠过程中仍然保留着锁,有锁只要睡眠时间到就能立刻执行)。

wait()是Object类的方法,主要作用是使执行代码的线程进行等待(把线程放入等待队列中),释放当前的锁,满足一定条件时被唤醒,重新尝试获取这个锁。

**注意:

  1. wait 要搭配 synchronized 来使用,脱离 synchronized 使用 wait 会直接抛出异常。
  2. 调用wait()方法的前提是首先要获取该对象的锁(synchronize对象锁)。
  3. 调用wait()方法会释放锁,本线程进入等待队列等待被唤醒,被唤醒后不是立即恢复执行,而是进入阻塞队列,竞争锁。

7. sleep() 与 wait() 方法的区别

wait方法是Object类提供的方法,需要搭配synchronized锁来使用,调用wait方法会释放锁,线程进入WAITING状态,等待被其他线程唤醒或者超时自动唤醒,唤醒之后的线程需要再次竞争synchronized锁才能继续执行。

sleep方法是Thread类提供的方法,调用sleep方法的线程进入TIMED_WAITING状态,不会释放锁,时间到自动唤醒。

8. 唤醒方法notify()

方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。

如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。(并没有 “先来后到”)

在notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。

notify():随机唤醒一个处在等待状态的线程。

notifyAll():唤醒所有处在等待状态的线程。
  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值