线程状态图 :
图来自 Java 线程的 6 种状态及切换(透彻解说)
初始、就绪、运行、期待、阻塞(synchronized)、终止。
Thread.sleep(millis)肯定工夫后主动复原执行,不开释对象锁 。
Object.wait() 间接 开释锁 ,始终期待,晓得 notify()唤醒。
Thread1.join() 示意运行的线程阻塞本人,期待 Thread1 执行完,再执行上面语句。
yield()让出 cpu,不开释对象锁,进入就绪态, 随时可能再次运行。
只有运行态和就绪态之间波及到 CPU 资源的切换。(即 yield())
Thread 开启的 3 种形式
Thread、Runnable、Callable
- Thread
最简略的一种,间接继承 Thread,重写 run 办法。主类中 new ThreadName().start(); 则进去就绪态。 -
Runnable
- 实现 Runnable 接口,重写 run。主类中 new RunnableName().start();
- 实现 Runnable 接口,重写 run。主类中 new Thread(new Runnable()).start();
- Thread 类还有其余重载办法,如传入 ThreadGoup,Runnable 初始执行接口等等,以上两个最罕用。
Thread 类也是实现了 Runnable 接口,实际上都是调用的 Runnable 接口的 run()办法。
-
Callable
实现 Callable 接口,重写 call()办法。创立 FutureTask 对象 new FutureTask<>(CallableName); 再 new Thread(FutureTak).start(); 即可。FutureTask 间接实现了 Runnable 和 Future,所以理论调用的还是 Thread(Runnable)构造方法。Callable 接口只有一个办法 V call();
Future 接口蕴含 cancel、isCancelled、isDone、get 办法,用户获取返回值。(Futuretask 对 Future 接口中的办法进行了重写)
Executor 治理线程
- newFixedThreadPool 固定大小的线程池
- newCachedThreadPool 可扩大的
- newScheduledThreadPool 可调度的, 运行一次,反复运行等
- newSingleThreadPool 单线程池
- newWorkStealingPool 窃取别的线程池的线程
应用:
ExecutorService executor = Executors.newFixedThreadPool(3);
Future<String> future = excutor.submit(Callable);// 退出线程池
future.get();// 获取返回值
后盾线程 deamon
定义:程序运行时在后盾提供通用服务的线程,这种线程并不属于不可或缺的局部。后盾线程运行的前提是必须有至多一个非后盾线程运行。
Thread.setDeamon(ture); 必须在 start()前设置。
java.util.concurrent 包
-
CountDownLatch
同步多个工作,能够设置一个初值,任何在这个对象上调用 wait()都将被阻塞,晓得值变成 0,每个工作执行完调用 countDown 都使值减 1。初始值不能重置,只能始终减上来。CyclicBarrier 能够重置。
- CyclicBarrier
用于并发工作期待(相似 join),如:idm 多线程下载文件,最初进行文件整顿。能够重置初始值。 - DelayedQueue
用于延时队列(延时取出元素),队头的提早最长。 - PriorityBlockingQueue
优先级阻塞队列 - SemaPhore
信号量,容许 n 个工作同时拜访。
平安失败的原理
就是 CopyOnWriteArrayList 办法。
java.util.concurrent 包上面的所有的类都是平安失败的
疾速失败的异样:ConcurrentModificationException
乐观锁: version、CAS(compareAndSwap)(Atomic 包、ReentrankLock 就是具体实现)
乐观锁: synchroinized
java.nio.*
基于缓冲的流。
次要组成:Channel,Buffer,Selector
clear,flip,compact 区别:
ByteBuffer 中有 pos、lim、cap 来记录缓冲应用状况。
- clear:position=0,limit=capacity,【清空缓冲】
- flip:limit=postion;position=0;【读指针挪动缓冲头】
- compact: 未读完的数据,压缩到缓冲头。【压缩未读完数据】
整体流程:获取通道,调配缓冲,clear,read 一次,{flip, 解决读到的数据,compact,read 一次}
大括号 {} 中示意循环执行。
读的模板代码如下,根本大同小异。
void fileChannel(){
try {FileInputStream fis = new FileInputStream("content.txt");
FileChannel channel = fis.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);// 调配缓冲
//position 置为 0,limit 置为 capacity
byteBuffer.clear();
int read = channel.read(byteBuffer);
System.out.println(byteBuffer);
while (read!=-1){
//limit 置成 position 最初的位值, 再指针 position 调成 0
// 从头读。(position、capacity、limit)
byteBuffer.flip();
while(byteBuffer.hasRemaining()){System.out.print((char)byteBuffer.get());
}
// 把未读完的数据压缩至 0 -position,// 下一次从 position 到 limit 读
byteBuffer.compact();
read=channel.read(byteBuffer);
}
channel.close();
fis.close();}catch (IOException e){e.printStackTrace();
}
}
fileChannel 还有 tryLock(),lock()和 release()办法。tryLock 为非阻塞式,得不到锁就立马返回
IO 多路复用——selector【NIO 的重点】
一个选择器治理多个 Channel。
举荐优良博客:NIO 的三大组件