1. CPU核心数和线程数的关系
进程:计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
线程:执行进程的最小单位。
多线程:为了充分利用cpu设计的。cpu 核数目前有双核,三核,四核,六核等。
CPU核心数与最大线程数关系: intel 发明了超线程技术,CPU 核心数与最大线程数之间的关系为1:2, 通常很多线程池设计将,最大线程数设计成2 * N + 1,N 为CPU 核心数。
2. CPU 轮换机制
时间片轮转法(Round-Robin,RR)主要用于分时系统中的进程调度。为了实现轮转调度,系统把所有就绪进程按先入先出的原则排成一个队列。新来的进程加到就绪队列末尾。每当执行进程调度时,进程调度程序总是选出就绪队列的队首进程,让它在CPU上运行一个时间片的时间。时间片是一个小的时间单位,通常为10~100ms数量级。当进程用完分给它的时间片后,系统的计时器发出时钟中断,调度程序便停止该进程的运行,把它放入就绪队列的末尾;然后,把CPU分给就绪队列的队首进程,同样也让它运行一个时间片,如此往复。
3. java中线程的运行与终止
通常线程的启动,有三种形式:
A extends Thread
A implements Runnable
A implements Callable
前两者无法获取线程执行结果。
Callbable 和 Future 配合使用,可以获取线程执行结果。
单独使用Callbable 意义不大,只有一个call 接口,与Runnable 的run方法无本质区别。
4. Callable 与 Futrue 配合使用
image.png
Future 封装的函数如上。
可以通过isDone() 判断是否执行完毕
5. Callable 与 FutrueTask 配合使用
FutrueTask 集成自RunnableFuture,RunnableFuture 接口继承了Runnable, Future ,可以方便的获取isDone() 等结果。
public class Task implements Callable {
@Override
public String call() throws Exception {
Random rand = new Random();
TimeUnit.SECONDS.sleep(rand.nextInt(10)); //随机休眠
return Thread.currentThread().getName();
}
}
public class MyFutureTask extends FutureTask {
public MyFutureTask(Callable callable) {
super(callable);
}
@Override
public void done() {
try {
System.out.println(get() + "执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
public class CallableTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i< 10; i ++) {
Callable callable = new Task();
MyFutureTask futureTask = new MyFutureTask(callable);
executorService.submit(futureTask);
}
executorService.shutdown();
}
}
FutureTask在高并发环境下确保任务只执行一次,确保不管调用多少次callable 的call 方法,或者Runnable的run方法,都只会执行一次,这是由native 层支持的。
6. 线程的其他方法
yield()方法:使当前线程让出CPU占有权,但让出的时间是不可设定的。也不会释放锁资源,所有执行yield()的线程有可能在进入到可执行状态后马上又被执行。
join方法:把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。