java 基本知识之多进程与多线程

2019-12-30  本文已影响0人  瀚海网虫

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中线程的运行与终止

通常线程的启动,有三种形式:

  1. A extends Thread
  2. A implements Runnable
  3. A implements Callable

前两者无法获取线程执行结果。
Callbable 和 Future 配合使用,可以获取线程执行结果。
单独使用Callbable 意义不大,只有一个call 接口,与Runnable 的run方法无本质区别。

4. Callable 与 Futrue 配合使用

image.png

Future 封装的函数如上。
可以通过isDone() 判断是否执行完毕

5. Callable 与 FutrueTask 配合使用

FutrueTask 集成自RunnableFuture,RunnableFuture 接口继承了Runnable, Future<V> ,可以方便的获取isDone() 等结果。

public class Task implements Callable<String> {
    @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<String> 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。

上一篇 下一篇

猜你喜欢

热点阅读