多线程

相关概念

程序:指令和数据的有序集合

进程:执行程序的一次执行过程,是系统资源分配的单位

线程:一个进程可以包含多个线程,至少包含一个线程,线程是cpu调度和执行的单位

线程的三种创建方式

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口

继承Tread类

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

启动线程:子类对象.start()

实现Runnable接口

自定义线程类实现Runnable接口,重写run()方法编写线程执行体,创建线程对象,调用start()方法启动线程,可以避免单继承的局限性,推荐使用

启动线程:传入目标对象+Thread对象.start()

Lamda表达式

(params)->{ statements }

new Thread(()->System.out.println("多线程")).start()

线程状态

 

 

Thread t=new Thread();//线程进入创建状态
t.start();//线程进入就绪状态
t.run();//线程进入运行状态,获取到cpu资源也进入到运行状态
t.sleep();//线程进入阻塞状态,调用wait()或同步锁定时也进入阻塞状态,阻塞解除后重新进入就绪状态,等待cpu调度执行
//线程中断或者执行结束就会进入死亡状态,不能再次启动

线程方法

 

 

 线程休眠

  • sleep(指定毫秒数):设置阻塞时间
  • sleep()存在异常InterruptedException
  • sleep()时间达到后线程进入就绪状态
  • sleep可以模拟网络延时,倒计时
  • sleep不会释放锁

线程礼让

  • yield():让当前线程暂定,进入就绪状态
  • 让cpu重新调度,即当前线程有可能继续运行

Join

等待线程执行完毕后其他线程才能执行,期间其他线程阻塞

线程优先级

Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度那个线程来执行

线程的优先级用数字表示1-10

Thread.MIN_PRIORITY=1

Thread.MAX_PRIORITY=10

使用getPriority(),setPriority()来获取和设置优先级

优先级的设置要找start()方法之前

守护线程

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

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

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

守护线程如后台记录操作日志,监控内存,垃圾回收

线程同步

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

为了保证数据在被访问时的正确性,加入了锁机制synchronized,当一个线程获得对象的排它锁,其他线程就必须等待,使用后释放锁即可

同步的方法是synchronized关键字,包括两种用法

  • synchronized方法:public synchronized void method(){}  synchronized方法控制对对象的访问,每个对象都加了一把锁
  • synchronized块:synchronized(obj){} obj是同步监视器,就是该对象本身

同步监视器执行过程:

  • 第一个线程访问,锁定同步监视器,执行其中代码
  • 第二个线程访问,发现同步监视器被锁,无法访问
  • 第一个线程访问完毕,解锁同步监视器
  • 第二个线程访问,发现没有被锁,将其锁定并访问

死锁

两个或多个进程互相竞争资源就是死锁

产生死锁的四个必要条件

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

只要破坏其中任意一个或多个条件就能避免死锁

Lock

显示定义同步锁来实现同步

java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具

ReentrantLock类实现了Lock,可以显示的加锁和释放锁

Synchronized与Lock对比

  • Lock是显式的加锁(需要手动加锁和释放锁),synchronized是隐式锁,出了作用域自动释放锁
  • Lock只有代码块锁,synchronized有代码块锁和方法锁
  • Lock锁的性能更好
  • 优先顺序Lock>同步方法块>同步方法

线程通信

Java提供几个方法来解决线程之间的通信问题

  • wait():线程一直等待,直到其他线程通知,会释放锁
  • wait(long timeout):直到等待毫秒数
  • notify():唤醒一个处于等待状态的线程
  • notifyAll():唤醒一个对象上所有调用wait()方法的线程,优先级别高的先调用

这些方法只能在同步方法或者同步代码块中使用,否则会抛出异常

线程池

避免频繁的创建和销毁线程,实现重复利用

线程池接口ExecutorService和工厂类Executors

 

posted @ 2021-04-22 17:40  我还有头发  阅读(58)  评论(0编辑  收藏  举报