day_21 多线程

多线程

1.多线程
    1.1 程序、进程、线程
        程序:一组命令的集合,为了完成指定的功能,程序时静态概念,一般保存在硬盘当中
        进程:正在运行的程序,是一个动态概念,需要保存在内存当中,操作系统会分配对应的
            PID,当我们直接关闭某个进程的时候,该进程会在运行内存中被销毁
        线程:一个程序中,不同的执行分支,如果同一个时间节点允许多个线程同时执行时,
            我们称为多线程

            在Java中,main方法开始执行,就是一个线程,称为主线程

    1.2 并行和并发
        并行:多个CPU,同时执行多个任务
        并发:一个CPU,同时执行多个任务

        多线程并行 必须大于等于2 才行
        单核CPU没有多线程

    1.3 单核CPU和多核CPU
        1.单核CPU是一种假的多线程,因为在一个时间单元内只能执行一个线程的任务
        2.如果是多核,才能更好地发挥多线程的效率
        3.一个Java应用程序java.exe,其中至少有三个线程:main()主线程,gc()垃圾回收
        线程,异常处理线程。 当然如果发生异常,会影响主线程

    1.4 多线程优缺点和应用场景
        单个线程先后完成多个任务比多个线程完成用时更短

        优点:1.提高应用程序相应。对图形化界面更有意义,增强用户体验。
              2.提高计算机系统CPU的利用率
              3.改善程序结构。将既长又复杂的进程分为多个线程,独立运行,有利于理解和修改

        场景:程序需要同时执行多个任务
              程序需要实现一些需要等待的任务时
              需要一些后台运行的程序时

    1.5 线程创建
        1.5.1 Thread
            第一种:创建一个类,继承Thread类 并覆写run方法
                run方法等于是新线程中的main方法
                public void run(){}

        1.5.2 Runnable 
            第二种:创建一个类,实现Runnable接口,并覆写run方法
                class Processor implements Runnable{}

            //创建线程类对象
                Thread t1 = new Processor();
            //调用start方法,启动线程
                t1.start();

        1.5.3 继承和实现的区别
            区别:
                继承 Thread :线程代码存放Thread子类run方法中
                实现 Runnable:线程代码存在接口的子类的run方法
            实现方式的好处
                避免了单继承的局限性
                多个线程可以共享同一个接口实现类的对象,适合多个相同线程
                    来处理同一份资源
    
    1.6 优先级和常用方法
        1.6.1 优先级概述
            进程的优先级等级
                MAX_PRIORITY: 10
                MIN_PRIORITY: 1
                NORM_PRIORITY:5
            涉及方法:
                getPriority(): 返回线程优先值
                setPriority(int newPriority):改变线程的优先级
            说明:
                线程创建时继承父线程的优先级
                低优先级只是获得调度的概率低,并非一定是在高优先级线程之后被调用

        1.6.2 常用方法
            getName:获取线程的名字
            setNaem:设置线程的名字,如果不设置,默认是Thread-0开始依次递增
            setPriority():设置优先级,java中有1-10,10个优先等级
            getPriority():获取优先级等级
            static currentThread():获取当前线程对象
            static sleep():让当前线程进入睡眠状态
            currentThread:出现在哪个线程中,就获取哪个线程的对象
            sleep:出现在哪个线程中,就睡眠哪个线程,参数为long类型的毫秒数

    1.7 声明周期
        新建、就绪、运行、阻塞、死亡
        具体看笔记

    1.8线程控制
        图
        1.8.1 线程停止
            stop:终止某个线程执行,已过时,可能会导致死锁

        1.8.2线程合并
            join:让当前线程等待指定线程执行完再执行

            t1.join();      //等待t1线程执行完再继续执行

        1.8.3 Yield
            yield:静态方法,暂停当前正在执行的线程对象,
                    并执行其他等待中的线程、
                1 静态方法 意味着跟哪个对象调用没有关系,写在哪个线程中,哪个线程就让位
                2 给同优先级让位,不同优先级不让位

    1.9 线程同步
        1.9.1 概述
            当多个线程有可能同时操作同一个数据的时候,为了保证数据一致性,需要进行同步执行
            本质是同步数据,一种安全机制
            异步编程:线程之间是完全独立的,相互没有影响
            同步编程:线程之间不是完全独立的,相互可能有影响

            同步场景:
                多个线程可能在同一时间对数据进行更改操作,查询无所谓

        1.9.2 不同步带来的问题
            详见笔记

        1.9.3 解决方法
            1.方法锁
                synchronized是修饰符,如果加了那么该方法就只能有一个线程执行

            2. 语句块锁
                适用于只有部分代码需要同步
                synchronized(this){}

        1.9.4 synchronized
            synchronized(对象){} 成员语句块锁
            synchronized(类名.calss){} 静态语句块锁
            当访问一个对象中加锁的成员方法或者成员语句块锁时,该对象中所有加锁的成员方法
                和成员语句块锁全部锁定
            当访问一个类中加锁的静态方法或者静态语句块锁时,该对象中所有……全部锁定

            当前对象(相同数据)所有加锁的是相互排斥,不会同步进行

    1.10 Lock
        1.10.1 概述
            同故宫显式定义同步锁对象来实现同步
            每次只能有一个线程对Lock对象加锁,县城开始访问共享资源之前应先获得Lock对象

        1.10.2 使用
            //创建锁对象
            Lock lock = new ReentrantLock();
            public void withDraw(double money){
                lock.lock();                    //开始同步

                lock,unlock();                  //解锁
            }
        
        1.10.3 优缺点
            是显示锁,需要手动开启关闭,synchronized是隐式锁,自动开启,执行完关闭
            只有代码块锁,而synchronized支持方法和代码块锁
            需要JVM花费较少的时间来进行资源调度,性能相对较好,有很好的扩展性

            使用顺序:Lock锁 --> 同步代码块锁 --> 方法锁

    1.11 定时器任务
        1.11.1 概述
            定时器:计划任务
            只要有一个计划任务,就会开启一个线程,进行计时,到达指定时间后,由该线程来完成这个任务

        1.11.2 使用
            //1 要做的事,也就是任务对象
            //2 什么时候开始做,1000*5,就是5秒后开始
            //3 间隔时间,3秒
            Timer t = new Timer();
            t.schedule(new LogTimerTask(),1000*5,1000*3);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值