多线程一些基础笔记

多线程

  • 创建线程方式1:继承Thread类,重写run()方法,调用start开启线程

  • 创建线程方式2:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法

  • 注意:线程开启不一定立即执行,由CPU调度执行

Thread.start()线程开启

Thread.sleep(100) 模拟延时

Thread.currentThread().getName() 当前线程

静态代理

真实对象和代理对象都要实现同一个接口

代理对象要代理真实角色

好处

代理对象可以做很多真实对象做不了得事情

真实对象专注做自己得事情

lambda表达式

  • 理解Functional interface(函数式接口) 是学习java8 lambda表达式的关键所在。
  • 为什么要使用lmabda表达式
    • 避免匿名内部类定义过多
    • 可以让你的代码看起来很简洁
  • 函数式接口的定义
    • 任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口
    • 对于函数式接口,我们可以通过lambda表达式来创建该接口的对象
  • labda表达式总结:
    • lambda表达式只能有一行代码的情况下才能简化成为一行,如果有多行,那么就用代码快包裹
    • 前提是接口为函数式接口
    • 多个参数化也可以去掉参数类型,要去掉就都去掉,必须加上括号

线程休眠

  • sleep(时间)指定当前线程阻塞的毫秒数;
  • sleep存在异常InterruptedException;
  • sleep时间达到后线程进入就绪状态;
  • sleep可以模拟网络延时,倒计时等
  • 每一个对象都有一把锁,sleep不会释放锁

线程礼让

Thread.yield();

当线程执行的时候碰到Thread.yield();就会先退出来进入就绪状态,让另一个线程先跑。

注意:礼让有时候不一定能成功,看CPU心情

Join

  • join合并线程,待此线程执行完成后,在执行其他线程,其他线程阻塞

线程的状态

new - 就绪状态 - 阻塞状态 或者 运行状态 - dead 有五个状态

线程中断或者结束,一旦进入死亡状态,就不能再次启动

线程优先级

  • 现成的优先级用数字表示,范围从1-10,默认是5

    • //放置优先权
      .setPriority(3)
      // 表示最大的 10
      .setPriority(Thread.MAX_PRIORITY);
      //表示最小的1
      setPriority(Thread.MIN_PRIORITY);
      
    • //得到优先权,可以显示出几级
      Thread.currentThread().getPriority()
      
  • 注意

    • 优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这都是看CPU的调度

守护线程

  • 线程分为用户线程和守护线程

  • 虚拟机必须确保用户线程执行完毕

  • 虚拟机不用等待守护线程执行完毕

     //守护线程 
     .setDaemon(true);
    

线程同步

  • 由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制 synchronized,当一个线程获得对象的排他锁,独占资源,其他线程必须等待,使用后释放锁即可,存在以下问题:
    • 一个线程持有锁会导致其他所有需要此锁的线程挂起;
    • 在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题;
    • 如果一个优先级高的线程等待一个优先级低的线程释放锁 会导致优先级倒置,引起性能问题。
  • synchronized 同步方法 锁的对象就是变化的量,需要增删改的对象

同步块

在这里插入图片描述

死锁

  • 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或则多个线程都在等待对方释放资源,都停止执行的情形。某一个同步块同时拥有“两个以上对象的锁”时,就不会发生“死锁”的问题

死锁避免方法

  • 产生死锁的四个必要条件:

    1. 互斥条件:一个资源每次只能被一个进程使用。
    2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    3. 不剥夺条件:进程以获得的资源,在未使用完之前,不能强行剥夺。
    4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    上列出了死锁的4个必要条件,只要破其中一个或多个就可以避免死锁发生

线程通信

wait() :表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁

notifyAll() :唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度

线程池

  • 好处:

    1. 提高响应速度(减少了创建新线程的时间)
    2. 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
    3. 便于县线程管理

    使用线程池

    • ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor
      • void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable
      • Futuresubmit(Callabletask):执行任务,有返回值,一般用来执行Callable
      • void shutdown():关闭线程池
    • Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池
    //线程池
    public class Test13 {
          
          
        public static void main(String[] args) {
          
          
            //1.创建服务,创建线程池
            //.newFixedThreadPool(10); 参数为线程池的大小
            ExecutorService service = Executors.newFixedThreadPool(10);
            //线程池启动服务
            service.execute(new MyThread());
            service.execute(new MyThread());
            //2.关闭链接
            service.shutdown();
        }
    }
    class MyThread implements Runnable{
          
          
        @Override
        public void run() {
          
          
                System.out.println(Thread.currentThread().getName());
        }
    }
    

猜你喜欢

转载自blog.csdn.net/qq_45316925/article/details/108129488