线程间通信 线程优先级 Thread 线程池

1.线程间通信
    多个线程 操作同一个资源 但是操作的动作不同

    例如:
        银行卡  -->存钱 -->取钱
    线程的等待唤醒机制:
        wait() 等待 让线程进入冻结状态 放弃了执行权 等待的线程会放到等待池中
        notify() 唤醒 会唤醒等待池中的线程 唤醒的是第一个等待的线程
        notifyAll() 唤醒等待的所有线程
    例如:
        两个人一起吃饭 交替着吃
        我吃的时候 你别动
        你吃的时候 我不动

    是Object类中的方法
        必须在同步中使用 不然会抛出异常
        synchronized的锁 是任意对象
        等待 唤醒的 是持有该锁的线程
        所以 任意对象都可以调用 上述方法
        对于这种 任意对象都可以调用的方法 应该定义在Object类中

        只有同一个锁上的被等待线程 可以被同一个锁上的线程唤醒
2.生产者消费者模式
    先生产 再消费
    满足一个条件 需要先有商品 才能够消费
3.Thread类中的其他方法
    3.1 停止线程
        如何让一个线程结束 其实只有一种方法 就是让run()方法结束
            因为我们在实际操作线程时 多伴随循环
            1.定义循环结束标记 让循环结束
            2.使用interrupt()方法 中断线程

                如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,
                或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 
                方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。 
            wait() 将线程从运行状态 转到冻结状态
            notify() 唤醒 将线程从冻结状态 转到运行状态
            sleep(毫秒)线程进入冻结状态 但是他会自动醒来

            interrupt()属于不正常唤醒 会出现中断异常

    3.2 守护线程
        void setDaemon(boolean on) 将该线程标记为守护线程或用户线程。后台线程
        该方法必须在线程启动之前调用

        当后台线程开启后 会和 前台线程一样 都可以抢夺cpu的执行权
        但是 结束不一样 当所有的前台线程都结束后 后台线程会跟着自动结束

        唐僧 和 四个徒弟
            唐僧 前台线程
            四个徒弟 守护前台线程的后台线程
    3.3 加入线程
        void join() 等待该线程终止。 
            b.join(); //插队
        
         在A线程中 调用了 b线程的join方法
         表示 只有当 b线程执行完毕后 A线程才能继续执行
         A线程继续执行 才会启动其他线程
        
        void join(long millis) 等待该线程终止的时间最长为 millis 毫秒。

         在A线程中 调用了 b线程的join(10)方法
         表示 A线程 会等待 b线程执行10毫秒
         10毫秒过后 A线程 和 b线程并行执行
        
        当前线程暂停 当指定的线程结束后 当前线程继续执行
        Thread类的join方法 可以使线程之间的并行执行变为串行执行
    注意:
        1.jdk规定 join(0) 的意思不是等待0毫秒后 其他线程可继续
            而是 等价于 join()方法
        2.join方法必须在线程start方法调用之后才有意义
            如果一个线程都没启动 那它也就不能插队

    3.4 线程优先级
        线程的优先级 一共 10级
        从1~10 默认优先级是5
        static int MAX_PRIORITY 
              线程可以具有的最高优先级。 
        static int MIN_PRIORITY 
              线程可以具有的最低优先级。 
        static int NORM_PRIORITY 
              分配给线程的默认优先级。
              
        void setPriority(int newPriority) 更改线程的优先级。 
        public String toString()返回该线程的字符串表示形式,包括线程名称、优先级和线程组。 

    3.5 礼让线程
        static void yield() 暂停当前正在执行的线程对象,并执行其他线程。 
        /*当一个线程 调用了 这个方法后
         * 它就会把cpu执行权让掉 暂停当前正在执行的线程 并执行其他线程
         * 让线程执行的更加平均
        * */
4.线程池
    什么是线程池
        假设 一个服务器完成一项任务 需要的时间分为三部分
            1. 创建时间 T1
            2. 在线程中执行的时间 T2
            3. 销毁线程的时间 T3
        如果 T1 + T3 远大于T2 则可以采用线程池技术
        线程池的出现 可以提高服务器的性能
        如果并发的线程数量很多 并且每一根线程要执行的任务都很简短
        这样频繁的创建线程 就会大大降低系统的效率
        为了提高线程的复用性 就是执行完任务并不销毁 而是继续执行其他任务
        出现了线程池技术
    java提供了四种线程池
        1.无界限 线程池 可以自动回收线程
            static ExecutorService newCachedThreadPool() 
        2.固定大小 线程池
            static ExecutorService newFixedThreadPool(int nThreads) 
        3.固定大小 可根据时间启动
            static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 
        4.单线程 线程池
            static ExecutorService newSingleThreadExecutor() 
    
    execute()和submit()方法的区别
        1.可以接收的任务类型不同
            submit() -->Runable Callable
            execute()-->Runnable
        2.返回值不同
            submit() 有返回值
            execute()不确定的返回值 void

猜你喜欢

转载自blog.csdn.net/weixin_42738506/article/details/81510919