1 线程
线程:现代操作系统调度的最小单元,也叫轻量级进程。
设置线程优先级时,针对频繁阻塞(休眠/IO操作)的线程需要设置较高优先级,而偏重运算(需要较多CPU时间或者偏运算)的线程设置较低的优先级,确保处理器不会被独占。
线程的六种状态:
线程创建后,调用start()方法开始运行。当线程执行wait()方法之后,线程进入等待状态。进入等待状态的线程需要依靠其他线程的通知才能返回到运行状态;超时等待状态相当于在等待状态的基础上增加了超时限制,达到设定时间后会返回到运行状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入堵塞状态。线程在执行Runnable的run()方法之后将会进入到终止状态。
Java将线程的运行和就绪状态统称为运行状态。阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块时的状态,但是阻塞在java.concurrent包中的Lock接口的线程状态确实等待状态,因为java.concurrent包中的Lock接口对于阻塞的实现海军使用了LockSupport类中的相关方法。
Daemon线程:
这是一种支持性线程,因为它主要被用于程序中后台调度以及支持性工作。这意味着,当一个Java虚拟机中不存在非Daemon线程的时候,Java虚拟机将会退出。但是在JMM退出时Daemon线程中的finally块并不一定会执行,所以在构建Daemon线程时,不能依赖finally块中的内容来确保执行关闭或清理资源的逻辑。
2 启动和终止线程
线程start()方法:当前线程(即parent线程)同步告知虚拟机,只要线程规划器空闲,应立即启动调用start()方法的线程。
(自定义的线程最好能起个名字)
中断:线程的一个标识位属性。
countThread.interrupt();
Thread countThread =new Thread(two,"countThread");
countThread.cancel();
通过标识位或者中断操作cancel()的方法能够使线程在终止时有机会去清理资源,而不是武断的将线程中止。
3 线程间通信
3.1 volatile和synchronized关键字
任何线程对Object(由Synchronized保护)的访问,首先要获得Object监视器。如果获取失败,线程进入同步队列,线程状态变为BLOCKED。当访问Object的前驱(获得了锁的线程)释放了锁,则该释放操作唤醒阻塞在同步队列中的线程,使其重新尝试对监视器的获取。
3.2 等待通知机制
等待/通知方法任何Java对象都是具备的,因为其被定义在所有对象的超类java.lang.Object上。
等待通知的经典范式:
等待方遵循的原则:1.获取对象的锁 2.如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查 3.条件满足则执行对应的逻辑
synchronized(Object){
while(条件不满足){
对象.wait();
}
对应的处理逻辑
}
通知方遵循的原则:1.获取对象的锁 2.改变条件 3.通知所有等待在对象的线程
synchronized(对象){
改变条件
对象.notifyAll()
}
管道输入/输出流
与普通的文件输入输出或网络的输入输出的不通知之处在于,它主要用于线程之间的数据运输,而传输的媒介为内存。
主要有四种实现:PipedOutputStream,PipedInputStream,PipedReader,PipedWriter(前两种面向字节,后两种面向字符)
Thread.join() : 当前线程A等待Thread线程终止之后才从thread.join()返回。
ThreadLocal:线程变量,是一个以ThreadLocal对象为键,任意对象为值的存储结构。
一个线程可以根据以恶ThreadLocal对象查询到绑定在这个线程上的一个值。
fetchConnection()
4 线程应用实例
- 等待超时模式
- 数据库连接池
模拟从连接池中获取,使用和释放连接的过程,客户端获取连接的过程被设定为等待超时的模式,即在1000毫秒内如果无法获取到可用的连接,将会返回给客户端一个null。设定链接池的大小为10个,然后通过调节客户端的线程数来模拟无法获取连接的场景。