Chapter 12. 并发

12.1 并发与并行

  • 并发:指两个或多个事件在同一个时间段内发生。
  • 并行:指两个或多个事件在同一时刻发生(同时发生)。

在操作系统中,并发指的是在一段时间内宏观上有多个程序同时运行。

在单 CPU 系统中,每一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,而这个分时交替运行的时间是非常短的。

注意:单核处理器的计算机肯定是不能并行的处理多个任务的,只能是多个任务在单个CPU上并发运行。同理,线程也是一样的,从宏观角度上理解线程是并行运行的,但是从微观角度上分析却是串行运行的,即一个线程一个线程的去运行,当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为线程调度

在多个 CPU 系统中,则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行执行,即利用每个处理器来处理一个可以并发执行的程序,这样多个程序便可以同时执行。多核处理器,核 越多,并行处理的程序越多,能大大的提高电脑运行的效率。

12.2 线程与进程

  • 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程(即一个程序运行后至少有一个进程);进程也是程序的一次执行过程,是系统运行程序的基本单位。

  • 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行。一个进程中是可以有多个线程的(即一个进程中至少有一个线程),这个应用程序也可以称之为多线程程序。

    同一进程中的线程共享其进程中的内存(堆内存、方法区内存,但栈内存不共享,因为一个线程一个栈)和资源。

线程调度

  • 分时调度

    所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

  • 抢占式调度

    优先让优先级高的线程使用 CPU ,如果线程的优先级相同,那么会随机选择一个线程(体现出线程随机性),Java使用的是抢占式调度。大部分操作系统都支持多进程并发运行,几乎都支持同时运行多个程序。但实际上,CPU使用抢占式调度模式在多个线程间进行着高速的切换,对于CPU一个核而言,某个时刻只能指向一个线程,而CPU的在多个线程间切换速度十分块。

12.3 创建线程

12.3.1 继承Thread类以创建线程

Java使用 java.lang.Thread 类代表线程,所有线程对象都必须是Thread类或其子类的实例。每个线程实际上就是顺序执行一段代码。Java使用线程执行体来代表这段程序流,如下创建并启动多线程:

一、定义子类,覆写方法:

定义Thread类的子类,并覆写该类的run()方法(它代表线程需完成的任务,故称之为线程执行体)。

对于Thread类,其构造方法有:

  • public Thread()
  • public Thread(String name):以指定名字name创建新的线程对象
  • public Thread(Runnable target):带有指定目标target创建新的线程对象
  • public Thread(Runnable target, String name):创建一个带有指定目标target且指定名字为name的线程对象。

自定义线程类举例如下:

public class MyThread extends Thread{
public MyThread(String name){ //构造方法,指定线程名称
super(name); //需要调用父类Thread的String参数的构造方法,以指定线程名称
}
@Override
public void run(){
for(int i = 0; i < 10; i++){
System.out.println(getName() + ":" + i);
}
} //覆写run方法,完成该线程执行的逻辑
}

二、创建实例,启动线程:

创建线程,即创建了线程对象。接着调用线程对象的start方法以启动该线程。

对于Thread类,其常用方法有:

  • public String getName():获取当前线程名称。
  • public void start():使该线程开始执行,JVM调用此线程的run方法。
  • public void run():此线程要执行的任务在此处定义。
  • public static void sleep(long millis):使当前正在执行的线程以执行毫秒数millis暂停(暂时停止执行)。
  • public static Thread currentThread():返回对当前正在执行的线程对象的引用。

测试类举例如下:

public class JustTest {
public static void main(String[] args) {
System.out.println("这里是main线程");
MyThread mt = new MyThread("另一条新线程"); //创建自定义线程对象
mt.start(); //开启新线程
for(int i = 0; i < 10; i++){
System.out.println("main线程:" + i);
}
}
}

Java中,每个程序运行至少启动2个线程(main线程,及垃圾收集线程)。

12.3.2 实现Runnable接口以创建线程

对于java.lang.Runnable,我们只需覆写其run方法即可。

一、定义实现类,覆写方法:

定义Runnable接口的实现类,并覆写该接口的run方法(该方法体同样为该线程的线程执行体)

举例如下:

public class MyRunnable implements Runnable {
@Override
public void run(){
for(int i = 0; i < 20; i++)
System.out.println(Thread.currentThread().getName() + " " + i);
}
}

二、创建实例,启动线程

创建Runnable实现类的实例,并以此实例作为Threadtarget来创建Thread对象(对应于Thread的构造方法Thread(Runnable target)),注意,该Thread对象才是真正的线程对象。接着,调用线程对象的start()来启动线程。

public class JustTest {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread t = new Thread(mr, "另一线程");
t.start();
for(int i = 0; i < 20; i++){
System.out.println("主线程" + i);
}
}
}

Runnable对象仅作为Thread对象的targetRunnable实现类包含的run方法仅作为线程执行体,而实际的线程对象仍是Thread实例,只是该Thread线程负责执行其targetrun()方法。

相比于直接继承Thread类,实现Runnable接口所具有的优势:

  1. 多个相同的程序代码的线程能够共享同一资源;
  2. 避免Java中的单继承的局限性;
  3. 增加程序的健壮性,实现解耦操作,代码能被多个线程共享,代码与线程独立;
  4. 线程池只能放入实现RunnableCallable类线程,不能放入直接继承Thread的类;

12.3.3 匿名内部类方式 创建线程

使用匿名内部类的方式实现Runnable接口,覆写Runnable接口中的run方法,举例如下:

public class JustTest {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
for(int i = 0; i < 20; i++)
System.out.println("另一线程:"+i);
}
};
new Thread(r).start();
for(int i = 0; i < 20; i++){
System.out.println("main线程:" + i);
}
}
}

多线程这一模块的知识,暂时先学到这,咕一咕。

JavaSE 学习笔记06丨并发的更多相关文章

  1. JavaSE 学习笔记01丨开发前言与环境搭建、基础语法

    本蒟蒻学习过C/C++的语法,故在学习Java的过程中,会关注于C++与Java的区别.开发前言部分,看了苏星河教程中的操作步骤.而后,主要阅读了<Java核心技术 卷1 基础知识>(第8 ...

  2. JavaSE 学习笔记02丨对象与类

    Chapter 4. 对象与类 4.1 面向对象程序设计概述 面向对象程序设计(简称OOP),是当今主流程序设计范型.面向对象的程序是由对象组成的,每个对象(来自于标准库或自定义的)包含对用户公开的特 ...

  3. JavaSE 学习笔记08丨网络编程

    Chapter 14. 网络编程 14.1 计算机网络入门 当前节的知识点只是一个概述,更具体.详细的内容放在 计算机网络 中. 14.1.1 软件结构 C/S结构(Client/Server结构): ...

  4. JavaSE 学习笔记07丨IO流

    Chapter 13. IO流 13.1 File类 java.io.File类是文件(file)和目录(文件夹)(directory)路径名(path)的抽象表示,主要用于文件和目录的创建.查找和删 ...

  5. JavaSE 学习笔记05丨泛型、集合

    Chapter. 10 泛型 10.1 泛型程序设计 泛型,指可以在类或方法中预支地使用未知的类型.泛型程序设计(Generic programming),意味着编写的代码可被很多不同类型的对象所重用 ...

  6. JavaSE 学习笔记04丨异常

    Chapter 9 异常 异常:指程序在执行过程中,出现的非正常的情况,最终导致JVM非正常停止. 在Java等面向对象的编程语言中,异常是一个类,所有异常都是发生在运行阶段的(因为也只有程序运行阶段 ...

  7. JavaSE 学习笔记03丨继承、接口、多态、内部类

    Chapter. 5 继承 继承作为面向对象的三大特征之一,它是多态的前提.它主要解决的问题是共性抽取. Java中的继承,是单继承.多级继承的. 已存在的类,被称为超类.基类.父类(parent c ...

  8. javaSE学习笔记(17)---锁

    javaSE学习笔记(17)---锁 Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率.本文旨在对锁相关源码(本文中的源码来自JDK 8).使用场景进行举例,为读 ...

  9. JavaSE学习笔记(13)---线程池、Lambda表达式

    JavaSE学习笔记(13)---线程池.Lambda表达式 1.等待唤醒机制 线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同. 比如:线程A用来生成包子的,线程B用 ...

随机推荐

  1. 【算法】二叉树、N叉树先序、中序、后序、BFS、DFS遍历的递归和迭代实现记录(Java版)

    本文总结了刷LeetCode过程中,有关树的遍历的相关代码实现,包括了二叉树.N叉树先序.中序.后序.BFS.DFS遍历的递归和迭代实现.这也是解决树的遍历问题的固定套路. 一.二叉树的先序.中序.后 ...

  2. CodeForces 1093F Vasya and Array

    题意 给一个长度为 \(n\) 的整数序列 \(a\),其中 \(a_i\) 要么为 \(-1\),要么为 \(1\sim k\) 中的整数. 求出将所有 \(-1\) 替换为 \(1\sim k\) ...

  3. LORA串口无线数据透明传输终端ZSL311

    ZSL311是由成都众山科技生产销售的一款LORA串口无线数据透明传输终端,采用的是LoRa扩频技术来进行无线数据传输,同时提供RS485和RS232串口,为用户提供全透明数据传输模式.支持星形.Me ...

  4. Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道

    Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道 背景 上一讲我们介绍了创建子进程的方式.我们都知道,创建子进程是为了与父进程协作(或者是为了执行新的程序,参考 Linux ...

  5. 分布式文档存储数据库之MongoDB基础入门

    一.MongoDB简介 MongoDB是用c++语言开发的一款易扩展,易伸缩,高性能,开源的,schema free 的基于文档的nosql数据库:所谓nosql是指不仅仅是sql的意思,它拥有部分s ...

  6. 使用Haproxy代理rabbitmq集群,用keepalive保证haproxy高可用

    原文地址:https://www.jianshu.com/p/440b8e1d5339 使用Haproxy代理rabbitmq集群 上一篇文章教了rabbitmq集群搭建.但是这样搭建出来的集群是3个 ...

  7. 10、Django与Ajax

    AJAX准备知识:JSON 什么是 JSON ? JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻量级的文本数据交换格式 JS ...

  8. 把数据转化为JSON格式用ajax进行前后端交互

    接着在https://www.cnblogs.com/dong973711/p/10907733.html的基础上做验证. 从前端提交数据 前端页面,submit.html <!DOCTYPE ...

  9. Javascript的运行效率是原生代码的20%-30%

    所以jser们,写代码更仔细些吧. http://www.cnblogs.com/codemood/p/3213459.html

  10. 仿select下拉框

    默认状态下,灰色面板出现.当点击页面按钮以及灰色面板外区域时,面板消失;点击按钮,灰色面板出现;点击灰色面板区域,面板不能消失. 主要考察:事件冒泡与取消事件冒泡. 代码: <!DOCTYPE ...