2

Java 多线程总结

 3 years ago
source link: https://jinglingwang.cn/archives/thread
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

什么是进程

进程是程序运行资源分配的最小单位

进程是操作系统进行资源分配的最小单位,其中资源包括:CPU资源、内存空间、磁盘IO等。同一进程中的多条线程共享该进程的全部系统资源,而进程和进程之间是相互独立的。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。

进程可以分为用户进程和系统进程,凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;用户进程就是由用户启动的进程。

什么是线程

线程是CPU调度的最小单位,必须依赖于进程而存在

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的、能独立运行的基本单位。它可以与同属一个进程的其他线程共享进程所拥有的全部资源。

线程是无处不在的,任何一个进程都必须要创建线程。

什么是并行运行

并行是指“并排行走”或“同时实行或实施”。

在操作系统中是指,一组程序按独立异步的速度执行,无论从微观还是宏观,程序都是一起执行的。

举个例子:高速公路有4条车道,同时最多可以有4辆车“并排通行”,这里就是并行;

什么是并发运行

在操作系统中,并发是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。

举个例子:高速公路有4条车道,同时最多可以有4辆车“并排通行”,这里是并行,当第5辆车开上高速路上时,有一个车道上至少有两辆车,他们就没办法“并排通行”,只能等前面的车走了,后面的车才能走;

Java 中的线程模型与调度

结论就是对于Sun JDK 来说,它的Windows版本和 Linux 版本都是使用的一对一线程模型来实现的,即一条线程就映射到一条轻量级进程中,因为 Windows 系统和 Linux 系统提供的线程模型都是一对一的。

JAVA 使用的是抢占式调度方式

具体的介绍分析可以看另一篇文章;

Java 线程多种实现方式

  1. 继承 Thread 类

    public class MyThread extends Thread {
        public void run() {
            // ...by: [https://jinglingwang.cn/](https://jinglingwang.cn/)
        }
    }
  2. 实现 Runnable 接口

    public class MyRunnable implements Runnable {
        public void run() {
            // ...by: [https://jinglingwang.cn/](https://jinglingwang.cn/)
        }
    }
  3. 实现 Callable 接口

    public class MyCallable implements Callable<Integer> {
        public Integer call() {
            return 123;// by: [https://jinglingwang.cn/](https://jinglingwang.cn/)
        }
    }
  4. 线程池 Executors

    Executors.newSingleThreadExecutor();
    Executors.newCachedThreadPool();
    Executors.newFixedThreadPool(1);
    ...by: [https://jinglingwang.cn/](https://jinglingwang.cn/)
  5. 线程池 ThreadPoolExecutor

    executorService = new ThreadPoolExecutor(MAX_WORKER_THREADS, MAX_WORKER_THREADS,
                                           10L, TimeUnit.MINUTES,
                                           new LinkedBlockingQueue<Runnable>(),
                                           threadFactory);

Java 线程状态

源码Thread.State 说明了一切,一共6个状态

public enum State {
    // 才开始new  还没有调用start()方法;by: [https://jinglingwang.cn/](https://jinglingwang.cn/)
    NEW, 
    // 可运行状态, 正在运行或者等待操作系统资源
    RUNNABLE, 
    // 阻塞状态,在等待一个监视器锁(也就是我们常说的synchronized)
    //或者在调用了Object.wait()方法且被notify()之后也会进入BLOCKED状态
    BLOCKED,
    //等待状态,在调用了以下方法后进入此状态
    // 1. Object.wait()无超时的方法后且未被notify()前,如果被notify()了会进入BLOCKED状态
    // 2. Thread.join()无超时的方法后
    // 3. LockSupport.park()无超时的方法后
    WAITING,
    //超时等待状态,在调用了以下方法后会进入超时等待状态
    //1. Thread.sleep()方法后【本文由公从号“彤哥读源码”原创】
    //2. Object.wait(timeout)方法后且未到超时时间前,如果达到超时了或被notify()了会进入BLOCKED状态
    //3. Thread.join(timeout)方法后
    //4. LockSupport.parkNanos(nanos)方法后
    //5. LockSupport.parkUntil(deadline)方法后
    TIMED_WAITING,
    // 终止状态, 线程已经执行完毕
    TERMINATED;
}

线程状态运行示意图:

Aj2iaaR.png!mobile

线程的常用属性和方法

  • run(); 必须实现的方法
  • setPriority(); 设置优先级,默认值是5;getPriority();
  • setDaemon(true); 设置为守护线程 ,该方法必须在启动线程前调用
  • getState(); 线程状态
  • dumpStack(); 堆栈跟踪
  • sleep(); 睡眠指定的时间, 让出CPU的执行权, 但是 不会让出对象锁:lock:
  • yield(); 暂停当前正在执行的线程, 让出CPU的执行权执行其他线程,但是如果没有同等优先级的线程或者更高优先级的线程, 该方法将不起作用
  • wait(); Object上的方法, 会释放CPU执行权, 释放锁:lock:, wait()后会还要返回该对象锁, 当前线程必须拥有当前对象的锁, 如果当前线程不是此锁的拥有者, 会抛出异常, 所以wait() 必须在synchronized block中
  • notify(); 一个线程调用该方法后, 会 唤醒一个 在该共享变量上调用了wait()方法被挂起的线程, 一个共享变量上可能有多个线程在等待, 具体是唤醒哪一个线程是随机的, 其他线程还是继续阻塞等待!
  • notifyAll(); 会唤醒所有在调用notifyAll()前调用了wait()方法而被挂起的线程!
  • join(); 等待该线程终止
  • interrupt(); 中断线程 线程A调用运行中的线程B的interrupt()方法, 仅仅只是设置一个需要中段的标志, 线程B实际上并不会马上被中断
  • start(); 启动线程 ; by: https://jinglingwang.cn/
  • stop(); 停止线程 线程不安全,不推荐,已过时

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK