首页 > 其他分享 >15-线程基础

15-线程基础

时间:2023-12-07 23:13:25浏览次数:25  
标签:同步 15 Thread 基础 线程 run 方法 public

线程(基础)

image-20231206082951949

程序 program 简单来说就是我们写的代码

进程 正在运行中的程序

image-20231206083549914

进程产生线程

单线程: 同一时刻,只允许执行一个线程

多线程:同一时刻,可以执行多个线程

并发:同一时刻,多个任务交替执行 ---------单核 cpu 实现的多任务就是并发

并行:同一时刻,多个任务同时执行 -----------多核 cpu 可以实现并行, 也可能并发和并行同时存在

package com.wxledu.threaduse;

/**
 * @author 王鑫磊
 * @version 1.0
 * 演示通过继承 Thread 类创建进程
 */
public class Thread01 {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 cat  对象, 可以当做线程使用
        Cat cat = new Cat();

        // 启动线程
        cat.start(); // 最终会执行 cat 的 run 方法

        // 当 main 线程 启动一个子线程的时候,主线程不会阻塞,会继续执行
        // 这时主线程和子线程交替执行
        System.out.println("主线程不会阻塞,会继续执行" + Thread.currentThread().getName());  // 主线程的名字就叫 main
        for (int i = 0; i < 10; i++) {
            System.out.println(i);

            Thread.sleep(1000); // 让主线程休眠
        }
    }
}

// 1. 当一个类继承了 Thread 类 该类就可以当做线程使用
// 2. 我们会重写 run 方法,写上自己的的业务代码
// 3. run Thread 类实现了 Runnable 接口的 run 方法
/*
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
 */
class Cat extends Thread{
    @Override
    public void run() {
        // 写上自己的额业务逻辑

        int times = 0;
        while(true){
            // 每隔 1 s ,在控制台输出 “喵喵, 我是小猫咪”
            System.out.println("喵喵, 我是小喵咪" + (++times) + " " + Thread.currentThread().getName());

            // 让该线程休眠 1 s
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            if (times == 80){ // 如果输出了 8 次就退出
                break;
            }
        }

    }
}

实现 runnable 接口

说明:

java 是单继承,在某些情况下一个类可能已经继承了某个父类,在这个时候,用 Thread 类方法来实现创建线程显然就不可能了

java 设计者们提供了另外一种方式创建线程,就是通过 Runnable 接口的方式来创建线程

image-20231206150914129

setName 设置线程名称
getName 返回该线程的名称
start 使该线程开始执行
run 调用线程对象的 run 方法
setPriority 更改线程的优先级
getPriority 获得线程的优先级
sleep 在指定的毫秒数内让当前正在执行的线程休眠
interrupt 中断线程

用户线程和守护线程

用户线程:也叫工作线程,当线程的任务执行完或通知方式结束

守护线程: 一般为工作线程服务,当所有的用户线程结束,守护线程也就结束

常见的额守护线程 : 垃圾回收机制

image-20231207154106093

上图是现成的生命周期

Synchronized 非公平锁

线程同步机制

  1. 在多线程编程中,一些敏感的个人数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何同一时刻,最多只有一个线程访问,以保证数据的完整性
  2. 也可以这样理解:线程同步,即当有一个线程在对内存进行操作的时候,其他线程都不可以对这个内存的地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作
  • 同步具体方法 - Synchronized

1) 同步代码块

​ synchronized (对象){ // 得到独像的锁, 才能操作同步代码

​ // 需要被同步的代码

}

2) synchronized 还可以放在方法声明中, 表示整个方法- 为实现同步

​ public synchronized void m (String name){

​ // 需要被同步的代码

​ }

3) 如何理解:就好像某小伙伴上厕所前先把,门关上(上锁) 完事后再出来(解锁), 那么其他小伙伴就可以在使用厕所了

4) 使用 Synchronized 解决售票问题 , 把对票数的操作封装到 一个方法中 用 Synchronized 进行声明

互斥锁

  1. Java 语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性
  2. 每个对象都对应于一个可称为 “ 互斥锁的标记” 这个标记保证在任意时刻,只能有一个线程访问对象
  3. 关键字 synchronized 来与对象的互斥锁联系, 当某个独像与 synchronized 修饰时,表名该对象在唉任一时刻只能有一个线程访问
  4. 同步的局限性: 导致程序的执行效率降低
  5. 同步方法(非静态的) 的锁可以是 this 也可以是其他线程(要求是同一个对象)
  6. 同步方法(静态的) 的锁为当前类本身
  • 注意事项和细节
  1. 同步方法如果没有使用 static 修饰: 默认锁对象就是 this
  2. 如果方法使用 static 修饰 ,默认锁的对象:当前类.class
  • 实现落地步骤
  1. 需要先分析上锁代码
  2. 选择同步代码或同步方法
  3. 要求多个线程的锁对象为同一个即可

线程死锁

多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程时一定要避免死锁的发生

释放锁

  • 什么情况下不会释放锁
  1. 线程执行同步代码块或者同步方法的时候,程序调用了 Thread.sleep() Thread.yield() 暂停当前线程的执行不会释放锁
  2. 线程执行同步代码快的时候,其他线程调用了 该线程的 suppend() 方法,将该线程挂起,该线程不会被释放

提示:应尽量避免使用 supped() 和 resume() 来控制线程,方法不推荐使用

package com.wxledu.homework;

/**
 * @author 王XX
 * @version 1.0
 *
 * 要求
 * 1. 有两个用户分别从 同一张卡里取钱(总额 : 10000)
 * 2. 每次都取 1000 ,当余额不足时, 就不用取了
 * 3. 不能出现超取现象 => 线程同步问题
 */
public class Homework {
    public static void main(String[] args) {
        T t = new T();
        Thread thread1 = new Thread(t);
        thread1.start();
        Thread thread2 = new Thread(t);
        thread2.start();
    }
}

/*
class Qu extends Thread{

    public static int money = 10000;
    private static boolean loop = true;

    public void setLoop(boolean loop){
        this.loop  =loop;
    }

    // 定义一个取钱方法, 因为有多个用户,取同一张卡上面的钱
    public static synchronized void drawMoney(){
        if (money <= 0){
            System.out.println("当前余额不足,请改天来取");
            loop = false;
            return;
        }

        System.out.println(Thread.currentThread().getName() + "取了1000元,剩" + (money -= 1000));

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void run() {
        while(loop){
            drawMoney();
        }
    }
}

*/

// 1. 多个线程同时共享访问同一变量, 实现 Runnable

class T implements Runnable{
    private int money = 10000;

    @Override
    public void run() {
        while (true){

            // 多个线程互斥的对共享变量进行访问
            synchronized (this){
                if (money <= 0){
                    System.out.println("余额不足");
                    break;
                }

                money -= 1000;
                System.out.println(Thread.currentThread().getName() + "取了 1000 元, 剩" + money);
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

纸上得来终觉浅,绝知此事要躬行。

标签:同步,15,Thread,基础,线程,run,方法,public
From: https://www.cnblogs.com/tomlove/p/17884206.html

相关文章

  • 锁-基础篇
    分类公平锁/非公平锁可重入锁独享锁/共享锁互斥锁/读写锁乐观锁/悲观锁分段锁偏向锁/轻量级锁/重量级锁自旋锁synchronized有锁升级过程在JDK1.6之前,syncronized是一把重量级的锁在JDK1.8中,其实默认是轻量级锁,但如果设定了-XX:BiasedLockingStartupDelay=......
  • 2023-2024-1 20231402《计算机基础与程序设计》第十一周学习总结
    2023-2024-120231402《计算机基础与程序设计》第十一周学习总结作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第十一周作业这个作业的目标自学计算机科学概论第15,16章,《C语言程序设计》第10......
  • Linux-线程优先级学习
    概念Linux系统中常用的几种调度类为SCHED_NORMAL、SCHED_FIFO、SCHED_RR。SCHED_NORMAL:用于普通线程的调度类SCHED_FIFO和SCHED_RR是用于实时线程的调度类,优先级高于SCHED_NORMAL。内核中区分普通线程与实时线程是根据线程的优先级,实时线程拥有实时优先级(real-timepriority......
  • 前端学习-JavaScript学习-js基础-API02
    学习视频:黑马程序员视频链接事件监听三要素:事件源、事件类型、事件处理程序随机点名案例<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"&......
  • uml基础知识
    Uml常用的9种图可以分为静态图和动态图两种,其中常用的静态图5种,动态图4种,静态图:用例图,类图,包图,对象图,部署图动态图:顺序图,通信图,状态机图,活动图。类图(ClassDiagram)类图是UML中最常用的图之一,用于描述系统中类的结构。它展示了类之间的关系,包括继承、聚合、关联等。类图还可......
  • UML1500字总结
    一、基本概念如下图所示,UML图分为用例视图、设计视图、进程视图、实现视图和拓扑视图,又可以静动分为静态视图和动态视图。静态图分为:用例图,类图,对象图,包图,构件图,部署图。动态图分为:状态图,活动图,协作图,序列图。1、用例图(UseCaseDiagrams):  用例图主要回答了......
  • uml1500
    1.用例图用例图是UML中最常见的图之一,它主要用于描述系统的功能需求。用例图中包含了参与者(Actor)和用例(UseCase)两个主要元素。参与者是与系统交互的外部实体,而用例则表示系统的功能。画法: 用例图的画法相对简单,通过椭圆形表示用例,人形图标表示参与者。通过实线箭头表示参与者......
  • 2023-2024 20231302《计算机基础与程序设计》第十一周学习总结
    作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第十一周作业这个作业的目标计算机网络、网络拓扑、云计算、网络安全、Web、HTML,CSS,Javascript、XML作业正文https://www.cnblogs.com/9q2z2z......
  • UML各类基础知识总结
    1、UML关系泛化(也就是我们传统意义上的继承关系)子类继承父类,关系用extend关键字标识;关联可以说是一种属于关系,图中即说的是PhoneNumber类属于Master类,同时,除了一对一的关系之外,还可以用一对多、多对一、多对多的关联关系,除了单向关联之外,双向关联也是存在的;需要注意的是,在......
  • 天池AI练习生计划 - 第二期AI数学基础入门与实践,火热进行中!通关赢取双重礼品!
    机器视觉学术研究与产品研发专家雷明,带领您详细学习人工智能领域需要用到的数据知识点,从学习者蜕变为AI新星!轻松来闯关,即可领取双重礼品~实训培训证书:通关两个关卡即可领取阿里云定制长袖T恤:通关全部关卡即可领取活动地址:https://tianchi.aliyun.com/specials/promotion/math......