Java基础知识总结之多线程
1、基本概念
进程是程序的一次动态执行过程,是系统进行资源分配和调度运行的基本单位。
线程是进程的一个实体,它是比进程更小的的能够独立运行的基本单位。在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位。线程基本自己不拥有系统资源,只拥有一点在运行中必不可少的资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统内多个程序间并发执行的程度。它可与同属一个进程中的其他线程共享进程所拥有的全部资源。
2、引入线程与进程的目的
在OS中引入进程的目的是为了使更多的程序能够并发执行,以提高资源的利用率和系统的吞吐量。
引入线程的则是为了减少程序在并发执行时所付出的时间开销,使OS具有更好的并发性,以进一步提高资源的利用率和系统的吞吐量。
3、程序、进程与线程的关系
程序是保存在硬盘上的可执行代码,是一种静态的概念。
进程是一个程序在计算机上执行的过程,是一种动态的概念。
线程是进程的一部分,进程包含多个线程在运行。
形象的比喻:将计算机的CPU比作一座工厂,它承担了所有的计算任务。
由于单个CPU一次只能运行一个任务,所以此工厂一次只能供给一个车间。进程好比是这个车间,任何一个时刻CPU总是运行一个进程,其他进程处于非运行状态。
一个车间里有很多工人协同完成一个任务,线程好比车间里的工人,一个进程可以包括多个线程。
车间的空间是工人们共享的,这象征着一个进程的内存空间是共享的,每个其包括的线程可以使用这些共享内存。
可每间房间的大小不同,有些房间只能容纳一个人,比如厕所,里面有人的时候,其他人就不能进入。这代表一个线程使用某些共享内存的时,其他线程必须等它结束,才能使用这一块内存。
一个人防止他人进入的简单方法就是在门口加一把锁。先到的人锁上门,后来的人看见上锁就在门口排队,等锁打开在进入,这叫做“互斥锁”(Mutual exclusion,缩写 Mutex),防止多个线程同时读取某一块内存区。
具体比如: Word程序的源代码就是保存在硬盘上的可执行代码,是静态的,当启动Word程序时对于操作系统就相当于启动了一个进程,而在这个进程还有许多功能(如拼写检查)是通过一个个线程实现的。如果Word关闭了,则这些拼写检查的线程也将消失,但是如果拼写检查的线程关闭了,也并不会让Word的进程关闭。
4、任何线程一般具有5种状态:创建、就绪、运行、阻塞、终止
创建状态:新建一个线程对象可采用Thread类的构造方法来实现。
就绪状态:调用start()方法启动线程,此时线程进入线程队列排队,等待CPU的服务。
运行状态:调运线程对象的run()方法。
阻塞状态:在可执行状态下,如果调用sleep()、suspend()、wait()等方法,线程进入阻塞状态
只有当引起阻塞状态的原因消失时,线程才可以进入就绪状态。
死亡状态:调用stop()方法或run()方法执行结束时。
5、Java中的多线程
1.Java中的实现方式:
在Java中线要实现多线程操作有两种常用的手段: 一种是继承Thread类,另外一种是实现Runable接口。
通过继承Thread类实现多线程必然受到单继承的局限性的影响,并且实现Runable接口适合资源共享,所以一般来说,都是通过实现Runable接口来实现多继承。
两种方式都必须明确覆写run()方法,此方法为线程的主体。
继承Thread类要通过start()方法启动线程,而Runable接口还是要依靠Thread类的start()方法来启动线程。
2.Thread类与Runable接口的联系与区别:
联系:
1.Thread的类也是Runable接口的子类,但是Thread类中并没有完全实现Runable接口中run()方法,所以两种方式都必须明确覆写run()方法。
public class Thread extends Object implements Runnable
2.二者的操作方式类似于代理模式:
Thread类与Runable接口的子类都同时实现了Runable接口,之后将Runable的子类放到Thread类的构造器中,调用Thread类的start()方法启动线程。
区别:
1.启动线程的方式不同
2.局限性不同
3.实现Runable接口的对象可以方便的实现资源的共享,而继承Thread类则多个程序之间无法共享线程类的实例对象。
(原因:当继承Thread类实现多线程时,程序每新建一个线程都需要创建一个Thread类对象,Thread类对象的执行体run()方法是独立的,因此每个因此多个线程之间不能共享实例变量。 而以实现Runable接口的对象作为Thread对象的target,Runable实现类的run()方法仅作为Thread对象的线程执行体,而实际的的线程对象依然是Thread的实例。多个线程可以共享一个target,所以一多个线程共享一个Runable对象的实例变量。)
3.为什么启动线程时不能直接使用run()方法:
调用start()方法来启动线程,系统会把该run()当成线程的执行体来处理;但如果直接调用线程对象的run()方法,则run()将会被当做一个普通方法被执行,而不是线程的执行体。
6、死锁的概念
7、进程同步
在多道程序环境下,系统中各进程以不可预测的速度向前推进,进程的异步性对临界资源的访问会给系统造成混乱,造成了结果的不可再现性。为防止这种现象,引入进程同步的概念。
对于某些资源来说,其在同一时间只能被一个进程所占用。这些一次只能被一个进程所占用的资源就是所谓的临界资源(例如现实生活中的厕所就是一个典型的临界资源)。典型的临界资源比如物理上的打印机,或是存在硬盘或内存中被多个进程所共享的一些变量和数据等(如果这类资源不被看成临界资源加以保护,那么很有可能造成丢数据的问题)。
对于临界资源的访问,必须是互诉进行。也就是当临界资源被占用时,另一个申请临界资源的进程会被阻塞,直到其所申请的临界资源被释放。而进程内访问临界资源的代码被成为临界区。
解决同步问题的两种方式:
同步代码块
synchronized(同步对象){
...
//需要同步的代码;
}
同步方法
synchronized 关键字将一个方法声明为同步方法。
//synchronized的音标['sɪŋkrənaɪzd]
对于临界区的访问过程分为四个部分:
1.进入区:查看临界区是否可访问,如果可以访问,则转到步骤二,否则进程会被阻塞
2.临界区:在临界区做操作
3.退出区:清除临界区被占用的标志
4.剩余区:进程与临界区不相关部分的代码
8、线程池
引入原因:
系统启动一个新的线程的成本比较高,因为它涉及与操作系统交互。在这种情况下,使用线程池可以很好的提高性能。尤其是当程序中需要创建大量的生存期很短暂的线程时,更应该考虑使用线程池。
实现过程:
线程池在系统启动时即创建大量空闲的线程,程序将一个Runable对象传给线程池,线程池就会启动一个线程来执行run()方法,当run()方法结束后,该线程并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个Runable对象的run()方法。
其他优势:
线程池还可以有效的控制系统中并发进程的数量,通过设置线程池的最大线程数参数可以控制系统中并发线程数不超过此数,避免系统中包含大量并发线程导致JVM崩溃。
Java基础知识总结之多线程的更多相关文章
- Java基础知识强化之多线程笔记01:多线程基础知识(详见Android(java)笔记61~76)
1. 基础知识: Android(java)学习笔记61:多线程程序的引入 ~ Android(java)学习笔记76:多线程-定时器概述和使用
- Java基础知识回顾之五 ----- 多线程
前言 在上一篇文章中,回顾了Java的集合.而在本篇文章中主要介绍多线程的相关知识.主要介绍的知识点为线程的介绍.多线程的使用.以及在多线程中使用的一些方法. 线程和进程 线程 表示进程中负责程序执行 ...
- Java基础知识强化之多线程笔记05:Java中继承thread类 与 实现Runnable接口的区别
1. Java中线程的创建有两种方式: (1)通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中. (2)通过实现Runnable接口,实例化Thread类. 2. ...
- Java基础知识强化之多线程笔记05:Java程序运行原理 和 JVM的启动是多线程的吗
1. Java程序运行原理: Java 命令会启动Java 虚拟机,启动 JVM,等于启动了一个应用程序,也就是启动了一个进程.该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 m ...
- Java基础知识强化之多线程笔记06:Lock接口 (区别于Synchronized块)
1. 简介 我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式 ...
- Java基础知识强化之多线程笔记03:进程与线程 和 多线程的意义
1. 要想了解多线程,必须先了解线程,而要想了解线程,必须先了解进程,因为线程是依赖于进程而存在. 2. 什么是进程? 通过任务管理器我们就看到了进程的存在. 而通过观察,我们发现只有运行的程序才会出 ...
- Java基础知识强化之多线程笔记02:多线程之 面试题(常问)
1. 多线程有几种实现方案,分别是哪几种 ? 两种. 继承Thread类 实现Runnable接口 扩展一种:实现Callable接口.这个得和线程池结合. 2. 同步有几种方式,分别是什么? ...
- Java基础知识强化之多线程笔记07:同步、异步、阻塞式、非阻塞式 的联系与区别
1. 同步: 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.但是一旦调用返回,就必须先得到返回值了. 换句话话说,调用者主动等待这个"调用"的结果. 对于 ...
- Java基础知识强化之多线程笔记04:并行和并发 区别
1. 并发 和 并行区别 (1)并发:(单核) 并发,是在同一个cpu上同时(不是真正的同时,而是看来是同时,因为cpu要在多个程序间切换)运行多个程序. 并发是指两个任务都请求运行,而处理器只能按受 ...
随机推荐
- 判断一字串String中是否包含某一串字符串
String ostype = data.getString("osType").toUpperCase(); //转换为大写 if (ostype.contains(" ...
- wpf 依赖强制回调
依赖属性的强制转换加回调,后期自己再改 using System; using System.Collections.Generic; using System.Diagnostics; using ...
- SpringBoot 配置提示功能
目的 配置自动提示的辅助功能可以让配置写起来更快,准确率大大提高. springboot jar 包含提供所有支持的配置属性细节的元数据文件.文件的目的是为了让 IDE 开发者在用户使用 applic ...
- 判断浏览器是否支持指定CSS属性和指定值
/** * @param attrName 属性名 * @param attrVal 属性值 * @returns {boolean} */ function isCssAttrSupported(a ...
- ubuntu18.04 flink-1.9.0 Standalone集群搭建
集群规划 Master JobManager Standby JobManager Task Manager Zookeeper flink01 √ √ flink02 √ √ flink03 √ √ ...
- Scrapy 之如何发送post请求
import scrapy import json class PostSpider(scrapy.Spider): name = 'post' # allowed_domains = ['www.x ...
- Feeling after reading《Jane Eyre》
Yesterday I read and listened over the book named <Jane Eyre>, the book is very thoughtful, th ...
- [UWP] 为WinRT组件创建Nuget包
Nuget 是 dotnet 开发中必不可少的包管理工具,但不仅仅局限于 dotnet 项目,在 VS 中使用 C++ 开发的时候,也可以使用 Nuget 来引用第三方组件.同样也可以用 Nuget ...
- CSPS模拟 56
前十基本都A题了,只有$Dybala$.$Naito$和弱比$yxs$没有A题 $T1 Merchant$ 明明学过$nth element$但是由于不懂原理导致我用了个鬼畜的${U队}$来维护前$K ...
- 【gradle使用—gradle介绍】
Gradle基本组件 Gradle是一个框架,定义了一套自己的规则,所以要搞清楚Gradle,必须要遵守它设计的原则,下面我们要先搞清楚一些Gradle的概念: Gradle中,每一个待编译的工程是 ...