Java进程与线程

章节目录:

    • 一、线程
    • 二、进程
    • 三、线程与进程
    • 四、线程安全
    • 五、线程池
    • 六、结束语

你可能已经很熟悉多任务(multitasking),这是操作系统的一种能力,看起来就可以在同一时刻运行多个程序。

例如,在编辑或下载邮件的同时可以打印文件等场景。

一、线程

1.1 什么是线程?

  • 线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位

  • 一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。

  • 一个标准的线程由线程ID,当前指令指针PC,寄存器和堆栈组成。而进程由内存空间(代码,数据,进程空间,打开的文件)和一个或多个线程组成。

1.2 线程状态:

Java进程与线程_第1张图片

1.3 线程使用:

/* *
 * 实现Runnable接口
 * 在run()中编写业务逻辑
 */

public class ThreadSample implements Runnable {

    @Override
    public void run() {
        System.out.println("do something...");
    }


    public static void main(String[] args) {
        ThreadSample threadSample = new ThreadSample();
        // 创建线程
        Thread thread = new Thread(threadSample);
        // 执行
        thread.start();
        // do something...
    }
}

二、进程

2.1 什么是进程?

  • 进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体

  • 进程是一种抽象的概念,从来没有统一的标准定义。

  • 进程一般由程序,数据集合和进程控制块三部分组成:程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块包含进程的描述信息和控制信息是进程存在的唯一标志。

三、线程与进程

3.1 关系:

  • 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

  • 资源分配给进程,同一进程的所有线程共享该进程的所有资源。

  • 处理机分给线程,即真正在处理机上运行的是线程。

  • 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体。

3.2 区别:

  • 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;

  • 一个进程一个或多个线程组成线程是一个进程中代码的不同执行路线

  • 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程其他进程不可见

  • 线程上下文切换比进程上下文切换要快得多

四、线程安全

当多个线程共享对通用对象的访问时,它们可能彼此冲突,带来新的bug,程序也会因此受到破坏。

4.1 内部对象锁:

  • 概念:它是Java语言内置的一种机制。

  • 如果一个方法声明时有synchronized关键字,那么对象的锁保护整个方法。也就是说,要调用这个方法线程必须获得内部对象锁。

  • 使用方式

    /* *
     * 通过synchronized关键字修饰方法,来进行保护
     */
    
    public synchronized void method(){
        // do something...
    }

4.2 字段变量同步:

    /* *
     * 使用volatile关键字使字段同步。
     */

    private volatile boolean done;
    
    /* *
     * 使用final关键字,安全地访问一个共享变量。
     * 如果有多个线程更改和读取这个映射,仍然需要同步。
     */

    private final Map<String, Double> accounts = new HashMap<>();

4.3 高效的映射、集和队列:

  • java.util.concurrent包提供了映射、有序集和队列的高效实现。

  • 如:ConcurrentHashMap等…

  • 这些集合使用复杂的算法,通过允许并发地访问数据结构的不同部分尽可能减少竞争

五、线程池

构造一个新的线程开销有些大,因为设计与操作系统地交互。

如果你的程序中创建了大量的生命期很短的线程,那么不应该把每个任务映射到一个单独的线程,而应该使用线程池

线程池包含许多准备运行的线程。(事先将多个线程对象放到一个容器中,当使用的时候就不用new线程而是直接去池中拿线程即可)

5.1 :Callable与Future:

  • Runnable封装一个异步运行的任务,Callable与Runnable类似,但是Callable有返回值

  • Future保存异步计算的结果。

5.2 :常见线程池:

  • newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

  • newFixedThreadPool:创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。

  • newCachedThreadPool:创建一个可缓存的线程池,此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

  • newScheduledThreadPool:创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。

  • newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。

5.3 :线程池优势:

  • 第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

  • 第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

  • 第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

六、结束语


“-------怕什么真理无穷,进一寸有一寸的欢喜。”

微信公众号搜索:饺子泡牛奶

你可能感兴趣的:(Java,java)