做者:Greyhtml
原文地址:Java多线程学习笔记java
源码: Githubgit
线程就是轻量级进程,是程序执行的最小单位。github
多进程的方式也能够实现并发,为何咱们要使用多线程?编程
从底层角度上看,CPU主要由以下三部分组成,分别是:网络
T1线程在执行的时候,将T1线程的指令放在PC,数据放在Registers,假设此时要切换成T2线程,T1线程的指令和数据放cache,而后把T2线程的指令放PC,数据放Registers,执行T2线程便可。多线程
以上的整个过程是经过操做系统来调度的,且线程的调度是要消耗资源的,因此,线程不是设置越多越好。并发
有意义,由于线程的操做中可能有不消耗CPU的操做,好比:等待网络的传输,或者线程sleep,此时就可让出CPU去执行其余线程。能够充分利用CPU资源。ide
不是,由于线程切换要消耗资源。高并发
示例:
单线程和多线程来累加1亿个数。-> CountSum.java
和CPU的核数有关
最好是经过压测来评估。经过profiler性能分析工具jProfiler,或者Arthas
公式
N = Ncpu * Ucpu * (1 + W/C)
其中:
Ncpu是处理器的核的数目,能够经过Runtime.getRuntime().availableProcessors() 获得
Ucpu是指望的CPU利用率(该值应该介于0和1之间)
W/C是等待时间和计算时间的比率。
具体示例可见:HelloThread.java
线程刚刚建立,尚未启动
即:刚刚New Thread的时候,尚未调用start方法时候,就是这个状态
可运行状态,由线程调度器能够安排执行,包括如下两种状况:
- READY
- RUNNING
READY和RUNNING经过yield来切换
等待被唤醒
隔一段时间后自动唤醒
被阻塞,正在等待锁
只有在synchronized的时候在会进入BLOCKED状态
线程执行完毕后,是这个状态
打断某个线程(设置标志位)
查询某线程是否被打断过(查询标志位)
查询当前线程是否被打断过,并重置打断标志位
示例代码:ThreadInterrupt.java
以上两种方式都不建议使用, 由于会产生数据不一致的问题,由于会释放全部的锁。
若是不依赖循环的具体次数或者中间状态, 能够经过设置标志位的方式来控制
public class ThreadFinished { private static volatile boolean flag = true; public static void main(String[] args) throws InterruptedException { // 推荐方式:设置标志位 Thread t3 = new Thread(() -> { long i = 0L; while (flag) { i++; } System.out.println("count sum i = " + i); }); t3.start(); TimeUnit.SECONDS.sleep(1); flag = false; } }
若是要依赖循环的具体次数或者中间状态, 则能够用interrupt方式
public class ThreadFinished { public static void main(String[] args) throws InterruptedException { // 推荐方式:使用interrupt Thread t4 = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { } System.out.println("t4 end"); }); t4.start(); TimeUnit.SECONDS.sleep(1); t4.interrupt(); } }
示例代码: ThreadFinished.java