首页 > 技术文章 > Java多线程(lambda表达式)

xiafrog 2021-01-18 00:29 原文

Java多线程(lambda表达式)

线程创建

继承Thread类

  • 自定义线程类继承Thread类
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程

实现Rannable接口

由于java单继承的局限性,推荐使用此方法

  • 定义MyRunnable类实现Runnable接口
  • 实现run()方法,编写线程执行体
  • 创建线程对象,通过线程对象调用start方法(静态代理)
new Thread(MyRunnable).start();

实现Callable接口

  1. 实现Callable接口,需要返回值类型

  2. 重写call方法,需要抛出异常

  3. 创建目标对象

  4. 创建执行服务:

    ExecutorService ser = Executors.newFixedTreadPool(nThreads);
    
  5. 提交执行:

    Future<Boolean> result = ser.submit(MyCallable);
    
  6. 获取结果

    boolean r = result.get();
    
  7. 关闭服务

    ser.shutdownNow();
    

优点

  • 可以提供返回值
  • 可以抛出异常

静态代理模式

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

好处:

  • 代理对象可以做很多真实对象做不了的事情
  • 真实对象专注做自己的事情
new Thread(() -> {...}).start();

Lambda表达式

  • 函数式编程

  • 函数式接口

    • 只包含唯一一个抽象方法的接口
    • 使用lambda表达式来创建函数式接口的对象
  • (参数) -> 表达式\语句\代码块

    • 多个语句用{}
    • 参数可以去掉类型,要去掉都去掉
    • 单个参数可以省略括号

线程状态

  • 创建状态
  • 就绪状态
  • 阻塞状态
  • 运行状态
  • 死亡状态

状态观测

  • Thead.State state = thread.getState()
    • NEW:创建状态
    • RUNNABLE:运行状态
    • BLOCKED:阻塞,等待监视器锁定
    • WAITTING:阻塞,等待另一个线程执行动作
    • TIMEED_WAITTING:阻塞,等待另一个线程执行动作达到指定时间
    • TERMINATED

线程方法

线程停止

  • 建议使用flag让线程自己停下来
private boolean flag = true;
@Override
public void run(){
    while(flag){
        ...
    }
}
public void stop(){
    this.flag = false;
}

线程休眠sleep

  • 指定线程阻塞的毫秒数
  • 存在异常InterruptedException
  • 时间到后线程进入就绪状态
  • 不会释放线程锁

线程礼让yield

  • 让当前正在执行的线程暂停,但不阻塞
  • 将线程从运行状态转为就绪状态
  • 礼让不一定成功

线程阻塞join

  • 等待该线程执行完后,再执行其他线程
  • 当前线程阻塞

线程优先级setPriority

  • 范围1~10
    • Tread.MIN_PRIORITY = 1;
    • Tread.Max_PRIORITY = 1;
    • Tread.NORM_PRIORITY = 5;

守护线程setDaemon

  • 线程分为用户线程和守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 如:后台记录操作日志、监控内存、垃圾回收等

线程同步

  • 并发:多个线程同时操作同一个对象

  • 同时访问时,进入对象的等待池

  • 锁机制:synchronized方法和synchronized块

同步块

  • synchronized(Obj){ }
  • Obj称为同步监视器
    • 同步监视器可以是任何对象,推荐使用共享资源作为同步监视器
    • 同步方法中的同步监视器就是this
    • Obj得是同一个实例,才能锁住

死锁

  • 多个线程互相等待对方释放资源
  • 某一个同步块同时拥有两个以上对象的锁时,就可能会发生死锁

死锁产生的四个条件

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

Lock锁

  • JDK5.0开始,通过显式定义同步锁对象来实现同步
  • 常用Lock接口的实现类ReentrantLock(可重入锁)
private final ReentrantLock lock = new ReentrantLock();
lock.lock();
lock.unlock();

线程通信

在同步方法或同步代码块中使用:

  • wait():一直等待,会释放锁
  • wait(long timeout):等待指定毫秒数
  • notify():唤醒一个处于等待状态的线程
  • notifyAll():唤醒同一个对象上所有等待的线程

线程池

  • 提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。

  • ExecutorService:线程池接口,常见子类ThreadPoolExecutor

    • void execute(Runnable command)
    • Future submit(Callable task):
    • void shutdown()
  • Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

推荐阅读