线程与线程池

单核cpu与多核cpu:

        线程的并发和并行问题

多线程的创建:

        多线程程序创建:java.lang.Thread(实现了Runnable接口)
        //            1定义一个类实现Runnable接口,重写run方法(run方法中设置线程任务),new一个Thread(参数)对象,将实现类当作参数传进去(可以用匿名内部类)
        //                用Thread对象点start方法开启线程(可以用匿名对象)
        //            2将一个类继承Thread类,重写run方法,创建这个类对象,调用start方法开启线程

线程安全问题:  多线程程序,无共享数据时,无安全问题
        //                多线程程序,有共享数据时,有安全问题
        //        解决方案:等待与唤醒机制:让一个线程在访问共享数据时,无论其是否失去CPU执行权,让其他线程等待
        //                同步代码块;同步方法        --->Object类方法
        //                Lock锁机制,
        //        线程间通信:多线程在处理同一资源,但处理过程(线程任务)不同,为有效利用资源,用等待与唤醒机制解决
        //        线程安全解决:同步代码块 synchronized( 锁对象(也叫对象监视器) ){ //访问共享数据或可能出现线程安全问题的代码}
        //                        注意:锁对象可以用任意对象,其只是相当于一个形式,但必须保证多线程使用的锁对象是同一个
        //                        作用:将同步代码块锁住,只让一个线程在同步代码块中执行,
        //                        执行逻辑:发现synchronized-->发现锁对象-->拿走(其实是赋值)--->执行完代码块中内容-->归还(赋值)
        //                                                        --->被拿走了,阻塞,直到拿到锁定对象,继续执行

 Lock锁机制:Lock接口:抽象方法:void Lock();  void unLock()
        //                            实现类:ReentrantLock类
        //                            使用:1 在类中方法外(成员变量位置)创建ReentrantLock对象
        //                                2 在可能出现安全问题的方法前调用Lock()方法
        //                                3 代码后调用unLock()方法 ; unLock可以在finally代码块中,这样无论是否有异常,都释放锁

线程池:

        线程池:使线程得以复用,不必频繁创建与销毁
        //        底层原理:创建一个集合List,存储多个线程:使用时Thread t=List.remove(0)/removeFirst()取出 
        //                                        使用后List.add(t)/addLast() 归还
        //        Executors类:java.until包中
        //            静态方法:static ExecutorService newFixedThreadPool(int x) 创建固定线程数量的线程池,返回值是ExecutorService接口的实现类对象
        //        ExecutorService接口:java.until.concurrent包中
        //            抽象方法:Feture<?> submit(Runnable task) 将线程放入池(第一次调用),并开启线程任务,用完自动归还线程池
        //                    void shutdown()  销毁线程池
        //        使用:1 使用Executor类内静态方法newFixedThreadPool创建线程池
        //            2 创建线程(2种方法)
        //            3 调用ExecutorService接口中抽象方法submit,使线程并入线程池(第一次调用),并执行线程任务(执行run方法)
        //                    submit        继承Thread类的类的对象/    实现Runnable类的类的对象     / 实现Runnable类的类的对象用Thread包装后的Thread对象
        //            4 调用ExecutorSerivce接口中shutdown方法,销毁线程池(不建议执行)
        //            5 匿名内部类线程可以放入,但没有意义

线程注意:

        1 为什么不直接调用run方法,而是要start?
        main线程start又一线程,main线程不会阻塞的(调用会阻塞的)
        主线程结束,其他线程可能没有结束(线程间基本不会收到影响:除非自己设置)
        
        直接调run方法,就是主线程,调用,并没有开另一线程
        源码:start方法源码会执行 start0方法,这是一个人本地方法,会另开线程
            start0只是将线程转为了可运行状态,【不一定会立即执行run】-》取决于cpu自己

控制线程退出:
        程序执行完自动退出
        使用【变量】控制run方法的退出,run方法退出,线程就结束了
            给主线程一个set方法,主线程就可以控制其退出了

Thread补充方法    :
        设置/获取线程优先级:
            setPriority     MAX_Priority 10     等3个常量
            getPriority
        interrupt
            中断线程:但是不是结束线程,所以一般用于中断休眠的线程,唤醒它
        
        yield让出cpu,让其他线程执行,但是礼让时间不确定,所以也不一定礼让成功 
            (cpu资源越紧张,礼让的对象占用cpu越大,礼让的成功率就越高)
                -》cpu不会认为它跑的过来,就听你的,先跑礼让的
        join让线程插队(一定先执行完插入线程的所有任务)
        
    用户线程和守护线程:
        用户线程:就是工作线程
        守护线程:为工作线程服务的,当所有用户线程结束,守护线程自动结束
            常见的守护线程:垃圾回收机制
            将一个线程设置为守护线程:
                主线程开启t1线程,t1无限循环,主线程退出,要求t1线程也退出-》将t1做成守护线程
            在(主角线程)设置守护线程: 陪葬品线程.setDaemon(true)就行了
            但是,要先设置,再启动 陪葬品线程(否则有异常)
            
    线程的生命周期:
        Thread的state是enum枚举类型,有6个取值,也就是有6种状态
        
        new 尚未启动
        runnable正在执行  ready和running  即使是running态,其运行也要看操作系统和cpu调度的
        blocked被阻塞,等待
        waiting等待 另一个线程的特定动作
        timeed_waiting等待,另一个线程执行达到某一指定时间
        terminated已退出的线程
        
        Thread的getState方法可以获得状态
        
    线程死锁:
        a线程必须拿到b线程的占用资源才释放锁
        但是同时,b线程必须拿到a的资源才释放锁
        
        你先完成作业,才能玩手机
        你先让我玩手机,才写作业
    
    线程释放锁的情况:
        同步方法完成
        同步方法有break/return
        出现未处理的异常/error,不得已释放锁
        调用锁对象的wait方法,【线程会暂停,并释放锁】
        
    线程不会释放锁的情况
        sleep方法,线程会暂停,但不会释放锁
        yield方法,线程会暂停,但不会释放锁
        尽量不再使用/过时的方法:
            线程正在执行,其他线程调用该线程的suspend方法,将该线程挂起,该线程不会释放锁
            resume方法,会结束其挂起
            状态图的runnable状态的线程挂起【注意】

【重要】:一个线程控制另一个线程
        需要在线程中有 控制线程的对象 ,构造方法给其赋值(set方法赋值)
        或者在构造方法中,将其设置为守护线程
        (但是注意守护线程不是正常退出,而是立即中断,可能有代码执行不到)
        所以还是用第一种比较好,用变量进行控制
        
    【重要】:多线程共享数据与安全
        锁的对象一定要是一个
        数据量小,可能一直是一个线程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值