线程

350 阅读3分钟

线程

进程是执行程序的一次执行过程,是系统资源分配的单位,通常在一个进程中可以包含若干个线程,线程是CPU调度和执行的单位。

线程三种创建方式

  1. Tread clss:继承Tread类

    • 自定义线程类继承Tread类

    • 重写run()方法,编写线程执行体

    • 创建线程对象,调用start()方法启动线程

线程开启不一定立即执行由CPU进行调度执行,Tread也是实现了Runnable接口

  1. Runnable接口:实现Runnable接口
  • 实现Runable接口
  • 实现run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程

  • 推荐使用
  1. Callable接口:实现Callable接口(了解)
  • 实现Callable接口,需要返回值类型

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

  • 创建目标对象

好处:

  • 可以定义返回值
  • 可以抛出异常

静态代理模式

  • 真实对象和代理对象都要实现同一个接口
  • 代理对象要代理真实角色
  • 好处:代理对象可以做很多真实对象做不了的事情,真实对象专注做自己的事情

Lamda表达式

函数式接口:任何接口,如果只包含唯一的一个抽象方法,那么它就是一个函数式接口

对于函数式接口可以通过Lamda表达式来创建该接口对象

静态内部类

局部内部类

匿名内部类:没有类的名称 ,必须借助接口或者父类

线程状态

  • 线程停止:
  1. 建议线程正常停止,利用次数
  2. 建议使用标志位,设置一个标志位
  3. 不要使用stop或者destroy
  • 线程休眠 sleep

每个对象都有一个锁,sleep不会释放锁

  • 线程礼让

    1. 礼让线程,让当前正在执行的线程暂停但不阻塞

    2. 将线程从运行状态转为就绪状态

    3. 让cpu重新调度,礼让不一定成功看cpu的心情

    Thread.yield();

  • 线程强制执行

    thread.join()

  • 观测线程状态

    Thread.State state=thread.getState();

  • 线程优先级

    .setPriority();

  • 守护线程

    1. 线程分为用户线程(如main())和守护线程(如gc()线程)

    2. 虚拟机不用等待守护进程执行完毕,虚拟机必须确保用户进程执行完毕

    3. thread.setDaemon(true);默认是false,true为开启 守护进程

线程同步

多个线程操作同一个资源(队列+锁)

同步方法和同步块

  1. synchronized 方法控制对象的访问,每个对象都有一个锁,每个synchronized方法必须获得调用该方法得锁才能执行否则线程会阻塞,一旦执行就独占该锁直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁继续执行

  2. 同步块 synchronized (obj){}

  3. 方法里面需要修改的内容才需要锁,锁太多浪费资源

  4. 同步方法默认锁的是对象类的本身this,同步块锁任何对象锁变化的量(增删改的)

    synchronized (list){
    
    list.add(Thread.currentThread().getName())
    
    }
    

死锁

产生死锁的必要条件:

  1. 互斥条件
  2. 请求和保持条件
  3. 不可剥夺条件
  4. 循环等待条件

lock锁

显式定义同步锁对象来实现

ReentrantLock(可重如锁)类实现Lock

jvm将花费较少时间来调度线程,性能更好

private final ReentrantLock lock=new ReentrantLock();

线程协作

生产者和消费者模式

  • 生产者---缓存区---消费者

线程池

ExecutorService和Executors

 ExecutorService Service=Executors.newFixedThreadPool(10);
  Service.execute(new MyThreaad());
  Service.shutdown();