基本概念
- 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
- 线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。参考百度词库。
理解
- 线程池(thread pool)是线程的集合,内部提供了线程的管理,定时任务,周期任务等功能
- 线程(thread)是执行线程的任务的执行单元
- 线程任务(thread task)具体线程需要执行的一连串代码方法,通过Thead类的方法延展出去
- 线程共享资源(thread sharing resource)多个线程运行线程任务使用的同一个资源
掌握要点
- 创建线程任务,启动线程执行线程任务,停止线程任务
- 多个线程在使用共享资源的协调方式(加锁处理,加锁后等待通知)
- 线程异常处理方式
- 常见的线程设计模式
理解Java线程状态
参考地址:(https://www.uml-diagrams.org/java-thread-uml-state-machine-diagram-example.html)
sleep()方法不会释放自己持有的锁,wait()方法只有一个锁时会释放手里的锁,有多个时也不会释放
Java创建线程
- A类继承Thread类,重写线程任务run方法,new A().start()就是启动线程执行线程任务
- A类实现Runable接口的线程任务run方法,new Thread(new A()).start()就是启动线程执行线程任务
多个线程资源协调(参考状态图变化)
-
synchronized关键字,线程看到在线程任务代码中碰到synchronized关键,会对对应的资源上线程锁,其他线程看到已有线程就会阻塞等待持有线程锁的线程执行完成后再获取资源锁。
- 可以使用在方法上,静态方法加锁Class类,非静态方法加锁是对象
- 也可以使用在变量上,变量加锁是当前变量的对象
- 也可以synchronized(锁定对象){代码块}
-
使用锁定后主动等待通知的方式协调
- 使用锁定对象的方法wait(),notify(),notifyAll()
- 使用ReentrantLock和ReentrantReadWriteLock
- 扩展使用ReentrantLock的Condition。好处:condition在使用signal方法会去找当前condition关联的线程来激活。
线程池
线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。线程池内部有BlockQueue,没有执行的任务会放到队列中等待Idle的线程
常见线程池
- Executors.newSingleThreadExecutor():创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
- Executors.newScheduledThreadPool(int n):创建一个定长线程池,支持定时及周期性任务执行。
- Executors.newFixedThreadPool(int n):创建一个可重用固定个数的线程池,以共享的无界队列方式来运行这些线程。
- Executors.newCacheThreadPool():可缓存线程池,先查看池中有没有以前建立的线程,如果有,就直接使用。
线程异常处理(UncaughtExceptionHandler接口的实现类)
- 为线程绑定异常处理对象setUncaughtExceptionHandler
- 设定默认的异常处理对象setDefaultUncaughtExceptionHandler
线程辅助类(java.util.concurrent包下的类)
- Atomic相关类,对常用的基础对象进行了封装
- Concurrent集合类,对集合类进行了封装
- 多线程常用功能类,Semaphore类固定线程任务的执行数量;CountDownLatch达到多个线程任务后才统一执行;CyclicBarrier执行固定数量的线程任务后需要执行一次CyclicBarrier绑定的线程任务;Exchanger两个任务部分或全部功能是绑定到一起的,绑定的功能需要在exchange前完成
其他
创建线程指定线程组。不过暂时没怎么用过,都是用的线程池。可以为线程指定优先级通过setPriority(Thread.MAX_PRIORITY)。自定义线程池可以通过PriorityBlockingQueue实现任务的优先顺序。Java还提供一个volatile关键字来实现变量在各个线程中的可见性,不是原子性。具体要使用可以百度或参考深入理解Java虚拟机对这个字段的解释。