线程
1.基本概念
程序:指令的集合,静态的代码,静态的对象
进程:程序一次执行过程,有生命周期,动态
线程:进程的进一步划分
2.单核、多核CPU
2.1理解
单核cpu一个时间单元只能执行一个线程,多核支持多线程
Java应用程序至少有三个线程,main主线程,gc垃圾自动回收,异常处理线程
2.2并行和并发
并行:多个CPU同时执行多个任务
并发:一个CPU同时执行多个任务
2.3多线程优点
- 提高应用程序的响应。对图形化界面更有意义,可增强用户体验。
- 提高计算机系统CPU的利用率
- 改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和
修改
2.4应用
程序需要同时执行两个或多个任务。
程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、网络操作、搜索等。
需要一些后台运行的程序时。
3.线程的创建和使用
Thread类的特性:
每个线程都是通过某个特定的Thread对象的run()方法来完成操作的,run()方法的主题称为线程体
通过Thread对象的start()方法启动线程
方法一:创建类继承Thread类覆写run方法
方法二:实现Runnable接口,覆写run方法,启动线程调用Thread的start方法
4.常用方法
start() : 启动线程
setName() : 设置线程的名字,默认是Thread-0 , Thread-1 以此类推
getName() : 获取线程的名字
setPriority() : 设置优先级 , 1-10 , 10个级别,1最小,10最高
getPriority() : 获取优先级
Static currentThread() : 获取当前线程的内存地址(线程对象)
Static sleep() : 让当前线程进入睡眠状态,参数是毫秒数
5.生命周期
要想实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread类 及其子类的对象来表示线程,在它的一个完整的生命周期中通常要经历如下的五 种状态:
新建: 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建 状态
就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源
运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态, run()方法定义了线 程的操作和功能
阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出 CPU 并临时中止自己的执行,进入阻塞状态
死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束
6结束线程
stop:终止一个线程,容易导致死锁,已过时,不推荐使用
7.线程同步-锁
共享资源访问防止冲突,在一个任务访问时锁定该资源,其他任务无法访问
synchronized的锁:
任意对象都可作为同步锁,所有对象都自动含有单一的锁
同步方法的锁:静态方法类名.class 非静态方法this
同步代码块:自己指定,大多数this或类名.class
注意
必须确保使用同一个资源的多个线程共用一把锁
一个线程类中的所有静态方法共用同一把锁,所有非静态方法共用同一把锁
释放锁:
同步方法代码块执行结束,遇到break return,有未处理的error和exception,wait()方法
不会释放锁:Thread.sleep(),Thread.yield()
suspend()挂起
7.1修饰符synchronized
同步条件:必须多线程,多线程必须有可能同时共享一个数据,涉及数据的更改
方法锁:synchronized修饰符修饰的方法不能同时被多个线程执行
8.线程同步-lock
//锁对象
Lock lock = new ReentrantLock();
//加锁
lock.lock();
//解锁
lock.unlock();
synchronized与Lock对比
1.Lock是显式锁(手动开锁和关锁),synchronized是隐式锁,出了作用域自动释放
2.Lock只是代码块锁,synchronized有代码块锁和方法锁
3.使用Lock锁,JVM将花费更少的时间来调度线程,性能更好。并且具有更好的延展性
优先使用顺序:
Lock 同步代码块 同步方法
9.守护线程
又称兜底线程
默认有一个守护线程监听我们的正常程序
jvm退出,守护线程退出
Thread类中提供setDaemon()方法设置某个线程为守护线程