Java--多线程之并发,并行,进程,线程(一)_MinggeQingchun的博客-CSDN博客

Java--多线程之终止/中断线程(二)_MinggeQingchun的博客-CSDN博客_java中断线程

Java--多线程之join,yield,sleep;线程优先级;定时器;守护线程(三)_MinggeQingchun的博客-CSDN博客

Java--多线程之synchronized和lock;死锁(四)_MinggeQingchun的博客-CSDN博客

Java--多线程之生产者消费者模式;线程池ExecutorService(五)_MinggeQingchun的博客-CSDN博客

以下对并发、并行、进程、线程的理解引自 阿里巴巴技术专家 Hollis

Java并发编程

我们在使用多线程/进程编程时,经常会遇到并发和并行这两个名词,它们看起来是一个概念,都是“多个线程/进程同时执行”的意思,但实际上它们是有区别的,甚至说不是一码事

并行是指两个或者多个事件在同一时刻发生,而并发是指两个或多个事件在同一时间间隔发生。

并行是在不同实体上的多个事件,并发是在同一实体上的多个事件

并发是指一个CPU处理器同时处理多个任务
并行是指多个CPU处理器或者是多核的处理器同时处理多个不同的任务
并发是逻辑上的同时发生(simultaneous),并行是物理上的同时发生

一、并发

并发(Concurrent)

在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行

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

并发,就是通过一种算法将 CPU 资源合理地分配给多个任务,当一个任务执行 I/O 操作时,CPU 可以转而执行其它的任务,等到 I/O 操作完成以后,或者新的任务遇到 I/O 操作时,CPU 再回到原来的任务继续执行

早期计算机的 CPU 都是单核的,一个 CPU 在同一时间只能执行一个进程/线程,当系统中有多个进程/线程等待执行时,CPU 只能执行完一个再执行下一个

无论是Windows、Linux还是MacOS等其实都是多用户多任务分时操作系统。使用这些操作系统的用户是可以“同时”干多件事的

两个任务并发执行的过程

二、并行

并行(Parallel)

在同一时刻,有多条指令在多个处理器上同时执行

当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行,这种方式称之为并行(Parallel)

并发是针对单核 CPU 提出的,而并行则是针对多核 CPU 提出的。和单核 CPU 不同,多核 CPU 真正实现了“同时执行多个任务”

两个任务并行执行的过程

上图中双核 CPU 执行任务的数量恰好等于 CPU 核心的数量,是一种理想状态。但是在实际场景中,处于运行状态的任务是非常多的,尤其是电脑和手机,开机就几十个任务,而 CPU 往往只有 4 核、8 核或者 16 核,远低于任务的数量,这个时候就会同时存在并发和并行两种情况:所有核心都要并行工作,并且每个核心还要并发工作

如一个双核 CPU 要执行四个任务,它的工作状态如下图所示

每个核心并发执行两个任务,两个核心并行的话就能执行四个任务。当然也可以一个核心执行一个任务,另一个核心并发执行三个任务,这跟操作系统的分配方式,以及每个任务的工作状态有关系

1、并发针对单核 CPU 而言,它指的是 CPU 交替执行不同任务的能力;并行针对多核 CPU 而言,它指的是多个核心同时执行多个任务的能力。

2、单核 CPU 只能并发,无法并行;换句话说,并行只可能发生在多核 CPU 中

3、在多核 CPU 中,并发和并行一般都会同时存在,它们都是提高 CPU 处理任务能力的重要手段

三、进程

对于操作系统来说,一个任务,一个应用程序就是一个进程(Process)

如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就是启动一个记事本进程

四、线程

在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)

如在一个记事本上打字,画图等子任务,这些子任务之间共用同一个进程资源

进程当做资源分配的基本单元,线程当做执行的基本单元,同一个进程的多个线程之间共享资源

(一)单核CPU如何做到多线程并发

实际上,对于单个CPU的计算机来说,在CPU中,同一时间只能干一件事儿。为了看起来像是“同时干多件事”,分时操作系统是把CPU的时间划分成长短基本相同的时间区间,即”时间片”,通过操作系统的管理,把这些时间片依次轮流地分配给各个用户使用。

如果某个作业在时间片结束之前,整个任务还没有完成,那么该作业就被暂停下来,放弃CPU,等待下一轮循环再继续做.此时CPU又分配给另一个作业去使用。

由于计算机的处理速度很快,只要时间片的间隔取得适当,那么一个用户作业从用完分配给它的一个时间片到获得下一个CPU时间片,中间有所”停顿”,但用户察觉不出来,好像整个系统全由它”独占”似的。

所以,在单CPU的计算机中,我们看起来“同时干多件事”,其实是通过CPU时间片技术,并发完成的

Java中,默认就有两个线程:main主线程;GC垃圾回收线程

Java不能操作硬件CPU,因此也无法直接开启多线程,底层是调用本地方法C++的方法开启线程

/*** Causes this thread to begin execution; the Java Virtual Machine* calls the <code>run</code> method of this thread.* <p>* The result is that two threads are running concurrently: the* current thread (which returns from the call to the* <code>start</code> method) and the other thread (which executes its* <code>run</code> method).* <p>* It is never legal to start a thread more than once.* In particular, a thread may not be restarted once it has completed* execution.** @exception  IllegalThreadStateException  if the thread was already*               started.* @see        #run()* @see        #stop()*/public synchronized void start() {/*** This method is not invoked for the main method thread or "system"* group threads created/set up by the VM. Any new functionality added* to this method in the future may have to also be added to the VM.** A zero status value corresponds to state "NEW".*/if (threadStatus != 0)throw new IllegalThreadStateException();/* Notify the group that this thread is about to be started* so that it can be added to the group's list of threads* and the group's unstarted count can be decremented. */group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}}private native void start0();

(二)线程创建的三种方式

1、继承java.lang.Thread类,重写run方法

/**1、实现线程有3种方式:1、编写一个类,直接继承java.lang.Thread,重写run方法2、编写一个类实现java.lang.Runnable接口3、编写类实现Callable接口,通过FutureTask创建2、启动线程调用线程对象的start()方法start()方法的作用:启动一个分支线程,在JVM中开辟一个新的栈空间run()方法不会启动线程,不会分配新的分支线程栈*/
public class ThreadNewByExtend {public static void main(String[] args) {// 这里是main方法,这属于主线程,在主栈中运行// 新建一个分支线程对象Mythread t = new Mythread();/*** run()方法不会启动线程,不会分配新的分支栈(只调用run()不调用start()还是单线程)* 会先执行 t 线程的 for循环,再执行 主线程main中的for循环* *///t.run();/*** start()方法的作用:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成之后,瞬间就结束了* start()方法只是为了开启一个新的栈空间,只要新的栈空间开出来,start()方法就结束了,线程就启动成功了* 启动成功的线程会自动调用run方法,并且run方法在分支栈的栈底部(压栈)* run方法在分支栈的栈底部,main方法在主栈的栈底部;分支线程run和 主线程main是平级的* */t.start();//主线程for循环for (int i = 1;i <= 100;i++){System.out.println("main----" + i);}}
}class Mythread extends Thread {//Ctrl+O@Overridepublic void run() {for (int i = 1;i <= 100;i++){System.out.println("Mythread----" + i);}}
}

start()方法:

启动一个新线程,并会调用run()方法

通过start()方法来启动的新线程,处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行相应线程的run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程随即终止。

start()不能被重复调用

用start方法来启动线程,真正实现了多线程运行,即无需等待某个线程的run方法体代码执行完毕就直接继续执行下面的代码。这里无需等待run方法执行完毕,即可继续执行下面的代码,即进行了线程切换。

run() 方法:

不会启动新线程;run()就和普通的成员方法一样,可以被重复调用

直接调用run方法,并不会启动新线程!程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到多线程的目的

1、start() 可以启动一个线程,run()不能

2、start()不能被重复调用,run()可以

3、start中的run方法可以不执行完就继续执行下面的代码,即进行了线程切换。直接调用run方法必须等待其代码全部执行完才能继续执行下面的代码

4、start() 实现了多线程,run()没有执行多线程

start()方法新建一个线程并调用其run()方法;run()方法不能新建一个线程,只是thread的一个普通方法调用,是在当前线程中调用run()方法

2、编写类实现java.lang.Runnable接口

/**编写一个类实现java.lang.Runnable接口*/
public class ThreadNewByRunnable {public static void main(String[] args) {MyRunnable runnable = new MyRunnable();Thread t = new Thread(runnable);t.start();//采用匿名内部类方式Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1;i <= 100;i++){System.out.println("分支线程t1----" + i);}}});t1.start();//主线程for循环for (int i = 1;i <= 100;i++){System.out.println("main----" + i);}}
}class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 1;i <= 100;i++){System.out.println("分支线程t----" + i);}}
}

3、编写类实现Callable接口,通过FutureTask创建(JDK8新特性)

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;/**
实现线程的第三种方式:实现Callable接口优点:可以获取到线程的执行结果缺点:效率比较低,在获取t线程执行结果的时候,当前线程受阻塞,效率较低*/
public class ThreadNewByCallable {public static void main(String[] args) {// 创建一个“未来任务类”对象,参数:Callable接口实现类对象FutureTask task = new FutureTask(new Callable() {@Override// call()方法就相当于run方法,这个方法有返回值public Object call() throws Exception {System.out.println("call begin");Thread.sleep(1000 * 5);System.out.println("call end");return 100+50;}});Thread t = new Thread(task);t.setName("t");t.start();try {// get()方法获取t线程的返回结果,但是会导致“当前线程阻塞”Object obj = task.get();System.out.println("线程执行结果:" + obj);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}// main方法这里的程序要想执行必须等待get()方法的结束,而get()方法可能需要很久// get()方法是为了拿另一个线程的执行结果System.out.println("Hello World!");}
}

(三)线程常用方法

/**
1、获取当前线程对象Thread t = Thread.currentThread();
2、获取线程对象的名字String name = 线程对象.getName();
3、修改线程对象的名字线程对象.setName("线程名字");
4、当线程没有设置名字的时候,默认的名字Thread-0Thread-1.....*/
public class ThreadMethod {public static void main(String[] args) {//获取当前线程对象,currentThread()Thread t = Thread.currentThread();//获取线程名字"main",getName()System.out.println(t.getName());Thread t1 = new Thread();Thread t2 = new Thread();//线程默认名字:Thread-0;Thread-1System.out.println(t1.getName());//Thread-0System.out.println(t2.getName());//Thread-1//设置线程名字,setName()t1.setName("t1");System.out.println(t1.getName());//t1}
}

(四)线程调度,线程优先级

(1)线程调度模型

【1】抢占式调度模型:
            哪个线程的优先级比较高,抢到的CPU时间片的概率就高一些/多一些
            java采用的就是抢占式调度模型

【2】均分式调度模型:
            平均分配CPU时间片。每个线程占有的CPU时间片时间长度一样

(2)线程调度方法

【1】实例方法:
            void setPriority(int newPriority) 设置线程的优先级
            int getPriority() 获取线程优先级
            最低优先级1
            默认优先级是5
            最高优先级10
            优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的。)
【2】静态方法:
            static void yield()  让位方法
            暂停当前正在执行的线程对象,并执行其他线程
            yield()方法不是阻塞方法。让当前线程让位,让给其它线程使用
            yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”
            注意:在回到就绪之后,有可能还会再次抢到。
【3】实例方法:
            void join()

/*** 线程优先级** void setPriority(int newPriority)    设置线程的优先级* int getPriority()                    获取线程优先级** 最低优先级1;默认优先级是5;最高优先级10** */
public class ThreadPriority {public static void main(String[] args) {System.out.println("线程最高优先级:"+Thread.MAX_PRIORITY);//10System.out.println("线程最低优先级:"+Thread.MIN_PRIORITY);//1System.out.println("线程默认优先级:"+Thread.NORM_PRIORITY);//5//线程默认优先级System.out.println(Thread.currentThread().getName() + "线程的默认优先级是:" + Thread.currentThread().getPriority());Thread t = new Thread(new Runnable() {@Overridepublic void run() {for(int i = 0; i < 10000; i++){System.out.println(Thread.currentThread().getName() + "-->" + i);}}});t.setName("t");t.setPriority(10);t.start();Thread.currentThread().setPriority(1);// 优先级较高的,只是抢到的CPU时间片相对多一些。// 大概率方向更偏向于优先级比较高的。for(int i = 0; i < 10000; i++){System.out.println(Thread.currentThread().getName() + "-->" + i);}}
}

(五)线程状态图

线程是有状态的,并且这些状态之间也是可以互相流转的

Java中线程的状态分为6种:

1、初始(NEW):新创建了一个线程对象,但还没有调用start()方法

2、运行(RUNNABLE):Java线程中将就绪(READY)和运行中(RUNNING)两种状态笼统的称为“运行”。

(1)就绪(READY):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中并分配cpu使用权 。

(2)运行中(RUNNING):就绪(READY)的线程获得了cpu 时间片,开始执行程序代码

3、阻塞(BLOCKED):表示线程阻塞于锁

4、等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)

5、超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回

6、终止(TERMINATED):表示该线程已经执行完毕。

public class ThreadState {public static void main(String[] args) {Thread thread = new Thread(() -> {for (int i = 0; i < 5; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});//线程状态Thread.State state = thread.getState();System.out.println(state);//启动线程thread.start();state = thread.getState();System.out.println(state);while (state != Thread.State.TERMINATED){try {Thread.sleep(100);state = thread.getState();System.out.println(state);} catch (InterruptedException e) {e.printStackTrace();}}}
}

Java--多线程之并发,并行,进程,线程(一)相关推荐

  1. Java多线程、并发、进程和锁的详细讲解

    多线程 文章目录 多线程 ⼀.并发.并⾏.进程.线程概念 并发与并⾏ 线程与进程 线程调度: 二.创建线程 继承Thread类 实现Runnable接⼝ 二.线程常⽤⽅法 线程的优先级 线程的休眠 线 ...

  2. 【Java多线程】并发时的线程安全:快乐影院示例

    快乐影院示例 如果去掉71行的synchronized,会导致线程不安全 结果就是:明明已经没有票(有人抢先一步),却又被成功订走了.图见文末 下面是正确的代码: package cn.hanquan ...

  3. JAVA多线程和并发基础面试问答

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在 ...

  4. ***JAVA多线程和并发基础面试问答

    多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观 ...

  5. JAVA多线程和并发面试问题

    转载自   JAVA多线程和并发面试问题 Java多线程面试问题 1.进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程 ...

  6. JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  7. JAVA多线程和并发基础面试题

    多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观 ...

  8. java多线程与并发原理

    三.java多线程与并发原理 1.进程和线程的区别: 进程和线程的由来: (1)串行:初期的计算机只能串行执行任务,并且需要长时间等待用户输入: (2)批处理:预先将用户的指令集集中成清单,批量串行处 ...

  9. Java多线程编程-(4)-线程间通信机制的介绍与使用

    上一篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地Th ...

  10. Java多线程与并发相关 — 原理

    Java多线程与并发相关 - 原理 一 synchronized同步 1. 线程安全问题的主要诱因? 存在共享资源(也称临界资源); 存在多条线程共同操作这些共享数据; 2. 解决办法. 同一时刻有且 ...

最新文章

  1. myeclipse 提示为空白的问题
  2. 如何在剃须刀中使用三元运算符(特别是在HTML属性上)?
  3. 证书重复冲突问题:Command /usr/bin/codesign failed with exit code 1
  4. uclibc和glibc的差别
  5. centos7.5可以安装mysql_Linux(Centos7.5)安装Mysql
  6. mysql 优化20点
  7. android安卓应用和OBD的集成场景
  8. access ole 对象 最大长度_Redis 数据结构和对象系统,有这 12 张图就够了!
  9. NQueens, NQueens2 N皇后问题,递归回溯
  10. python sorted下标_Python列表操作最全面总结
  11. Pytorch采坑记录:DDP加载之前的checkpoint后loss上升(metric下降)
  12. python使用ssh 中文_使用Python进行SSH的最简单方法是什么?
  13. 非阻塞IO发送http请求
  14. 台风怎么看内存颗粒_内存应该怎么选?看完你就知道了。影驰 星曜 DDR4-3000 8G 内存测评(RGB真的强)...
  15. 玩~成语接龙c++代码
  16. 我们都应该停止三种测试实践
  17. 纳什效率系数与可决系数的差异
  18. 在Delphi程序中调用控制面板设置功能
  19. 苹果套路直播计算机隐藏版,套路计算器app,套路计算器隐藏官网版app预约 v1.0 - 浏览器家园...
  20. android zuk彩蛋,联想ZUK Z2你真的会玩吗?来看U-Touch 2.0的那些小彩蛋

热门文章

  1. linux下autocad完美替代品ARES Commander的安装运行
  2. CSDN博客里的大学生活简历——共勉
  3. 魅族20pro参数配置 魅族20pro值得买吗
  4. hive-SQL中将表压扁,字段变多
  5. Android 上传头像(文件)到服务器
  6. mysql的连接配置时区语句
  7. 社群发现算法--强连通和连通在关联图谱中的应用
  8. erlang游戏服务器
  9. 计算机毕业设计SSM超市商品管理系统【附源码数据库】
  10. 下载苹果官网视频的方式