当前仍在编辑文章 - Java 并 发 编 程 基 础

简介: 当前仍在编辑文章 - Java 并 发 编 程 基 础

Java 并 发 编 程 基 础


1. 概述

在支持同时运行多个任务的系统中,一个任务一般是一个程序,每个程序就是一个进程。而在一个程序其内部,可能包含了多个顺序执行流,每个顺序执行流就是一个线程。

比如在Windows操作系统中,我们可以通过系统自带的任务管理器查看到进程列表。某些进程可以展开,可能会查看到一个或者多个运行的服务或子进程。

1.1 进程与线程

【进程】:进行中的程序。是内存正在执行中的应用程序及其某些必要资源总和,它是线程的容器

  • 程序进行起来他就成了进程
  • 一个程序运行起来可能有多个进程:一种情况是,一个应用程序可以启动多个处理进程,所有进程隶属于当前应用程序即所谓的多进程服务。另一种情况是,一个程序只有一个进程,但开启了多个该程序。

进程一般有如下特征

  • 独立性:进程是系统中独立存在的实体。它可以拥有自己独立的资源。每个进行都有总计私有的地址空间。在没有经过进程允许时,一个用于进程不可以直接访问其它进程的地址空间。
  • 动态性:程序知识一个静态的指令集合,而进程是一个正在系统中活动的指令集合。进程具有自己的生命周期和各种不同的状态,这些概念在程序中都是不具备的。
    并发性:多个进程可以在单个处理器上并发执行,且它们之间不会互相影响。

【线程】:线程是位于进程中的执行单元,它是CPU调度的基本单元。

  • 线程是操作系统分配CPU时间的基本实体
  • 线程是处理器调度的最小单位。

1.2 并发与并行

【并发】:多个任务在CPU上"快速轮换”执行,而实际上任意时刻CPU只能执行其中一个任务

【并行】:多CPU、多个任务真正同时地在执行。任意时刻多个CUP能同时执行多个任务,即并型才是真正地同时执行任务。

真正并行执行多任务只能在多核CPU上实现。但由于实践中任务数一般远远多余CPU的核心数,因此操作系统会把很多任务的轮流调度到多个核心上执行。对于用户来说,计算机扫描执行一轮又一轮,速度非常之快,直观感觉就像是在并行执行的了。


2. Java多线程技术

多线程扩展了多线程地概念,使得同一个进程可以同时并发处理多个任务。已经说过,线程(Thread)也称为轻量级进程(Lightweight Process),是进程地执行单元,而进程是线程地容器。

2.1 线程的生命周期

2.2 创建进程的三种方式

2.2.1 继承Tgread类

(1)继承Thread类,并重写run方法

run()方法就是线程执行体,即该线程需要完成的事情。


         

(2)创建Thread子类的实例,并调用strat()方法期待线程

2.2.2 实现Runnable接口

(1)实现Runnable接口,并重写run()方法;

(2)创建Runnable实现类的实例;

(3)以Runnable实现类的实例为target,创建Thread对象,再调用start方法启动线程。


         
2.2.3 实现Callable接口

创建Thread子类的实例并调用start()方法启动线程


         


2.3 多线程编程实例

【实例1】

         

附录 Thread类


thread是程序中的一个执行线程。Java虚拟机允许应用程序同时运行多个执行线程。

每个线程都有优先级。优先级较高的线程优先于优先级较低的线程执行。每个线程也可以标记为守护进程,也可以不标记。当在某个线程中运行的代码创建一个新的“线程”对象时,新线程的优先级最初被设置为等于创建线程的优先级,并且当且仅当创建线程是守护进程时,它才是守护进程。

当一个Java虚拟机启动时,通常有一个非守护线程(它通常调用某个指定类的名为“main”的方法)。Java虚拟机继续执行线程,直到出现以下任一情况:

  • Runtimeexit方法已被调用,安全管理器已允许退出操作发生。
  • 所有不是守护线程的线程都已经死亡,要么是从调用run方法返回,要么是抛出一个传播到“运行”方法之外的异常。

有两种方法可以创建新的执行线程。一种是将一个类声明为 Thread的子类。这个子类应该覆盖类 Threadrun方法。然后可以分配并启动子类的一个实例。例如,计算大于规定值的素数的线程可以写成如下形式:


class PrimeThread extends Thread {
   long minPrime;
   PrimeThread(long minPrime) {
       this.minPrime = minPrime;
   }
   public void run() {
       // compute primes larger than minPrime
       . . .
   }
}

下面的代码将创建一个线程并开始运行:

PrimeThread p = new PrimeThread(143);
p.start();

创建线程的另一种方法是声明一个实现Runnable接口的类。然后,该类实现“运行”方法。然后可以分配该类的一个实例,在创建 Thread时作为参数传递,并启动。另一种样式中的相同示例如下所示:


class PrimeRun implements Runnable {
    long minPrime;
    PrimeRun(long minPrime) {
        this.minPrime = minPrime;
    }
    public void run() {
        // compute primes larger than minPrime
        . . .
    }
}

下面的代码将创建一个线程并开始运行:

PrimeRun p = new PrimeRun(143);
 new Thread(p).start();

出于识别目的,每个线程都有一个名称。多个线程可以具有相同的名称。如果在创建线程时没有指定名称,则会为其生成一个新名称。

除非另有说明,否则将“null”参数传递给此类中的构造函数或方法将导致引发NullPointRexception

构造器

构造器 说明
Thread() 分配一个新的Thread对象。
Thread(Runnable target) 分配一个新的Thread对象。
Thread(Runnable target, String name) 分配一个新的Thread对象。
Thread(String name) 分配一个新的Thread对象。
Thread(ThreadGroup group, Runnable target) 分配一个新的Thread对象。
Thread(ThreadGroup group, Runnable target, String name) 分配一个新的Thread对象,使其以 target作为其运行对象,以指定的name作为其名称,并属于group所引用的线程组。
Thread(ThreadGroup group, Runnable target, String name, long stackSize) 分配一个新的Thread对象,使其以target作为其运行对象,以指定的name作为其名称,并属于 group所指的线程组,并具有指定的堆栈大小
Thread(ThreadGroup group, Runnable target, String name, long stackSize, boolean inheritThreadLocals) 分配一个新的Thread对象,使其以“目标”作为其运行对象,以指定的name作为其名称,属于 group引用的线程组,以指定的stackSize,并继承inheritable thread-local变量的初始值,如果inheritThreadLocalstrue
Thread(ThreadGroup group, String name) 分配一个新的Thread对象。

Field

修饰符和类型 成员变量 描述
static int MAX_PRIORITY 线程可以拥有的最大优先级
static int MIN_PRIORITY 线程可以拥有的最低优先级
static int NORM_PRIORITY 分配给线程的默认优先级

方法

修饰符和类型 方法 描述
static int activeCount() 返回当前线程组及其子组中活动线程数量的估计值
void checkAccess() 确定当前运行的线程是否有权修改此线程
protected Object clone() 由于线程不能被有意义地克隆,因此引发CloneNotSupportedException (克隆支持异常)
static Thread currentThread() 返回对当前正在执行的线程对象的引用。
static void dumpStack() 将当前线程的栈跟踪打印到标准错误流(standard error stream)
static int enumerate(Thread[] tarray) 将当前线程的线程组(thread group)及其子组(subgroups)中的每个活动线程复制到指定数组中
static Map<Thread,StackTraceElement[]> getAllStackTraces() Returns a map of stack traces for all live threads
ClassLoader getContextClassLoader() 返回此线程的上下文ClassLoader
static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() 返回线程因未捕获的异常而突然终止时调用的默认处理程序
long getId() 返回此线程的标识符
String getName() 返回该线程的名称
int getPriority() 返回该线程的优先级
StackTraceElement[] getStackTrace() 返回表示此线程堆栈转储的堆栈跟踪元素数组
Thread.State getState() 返回此线程的状态
ThreadGroup getThreadGroup() 返回该线程所属的线程组
Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() 返回当此线程由于未捕获的异常而突然终止时调用的处理程序
static boolean holdsLock(Object obj) 当且仅当当前线程持有指定对象的监视器锁时,返回 true
void interrupt() 中断这个线程
static boolean interrupted() 测试当前线程是否已被中断
boolean isAlive() 测试该线程是否是活动的
boolean isDaemon() 测试该线程是否是守护线程
boolean isInterrupted() 测试该线程是否已被中断
void join() Waits for this thread to die
void join(long millis) 等待此线程死亡的时间最多为“毫秒(milliseconds )”
void join(long millis, int nanos) 等待此线程死亡的时间最多为“毫秒millis”加上“毫微秒nanos”
static void onSpinWait() 表示呼叫者暂时无法继续进行,直到其他活动发生一个或多个动作
void run() If this thread was constructed using a separate Runnable run object, then that Runnable object’s run method is called; otherwise, this method does nothing and returns
void setContextClassLoader(ClassLoader cl) Sets the context ClassLoader for this Thread
void setDaemon(boolean on) Marks this thread as either a daemon thread or a user thread
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) 设置当线程由于未捕获的异常而突然终止时调用的默认处理程序,并且没有为该线程定义其他处理程序
void setName(String name) 将此线程的名称更改为等于参数name
void setPriority(int newPriority) 更改此线程的优先级
void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) 设置当此线程由于未捕获的异常而突然终止时调用的处理程序
static void sleep(long millis) 根据系统计时器和调度程序的精度和准确度,使当前正在执行的线程休眠(暂时停止执行)指定的毫秒数
static void sleep(long millis, int nanos) 使当前正在执行的线程休眠(暂时停止执行)指定的毫秒数加上指定的纳秒数,这取决于系统计时器和调度程序的精度和准确度
void start() 导致此线程开始执行;Java虚拟机调用这个线程的run方法
String toString() 返回此线程的字符串表示形式,包括线程的名称、优先级和线程组
static void yield() 给调度程序的提示,当前线程愿意让出它当前对处理器的使用
目录
相关文章
|
1天前
|
缓存 Java
Java并发编程:深入理解线程池
【4月更文挑战第26天】在Java中,线程池是一种重要的并发工具,它可以有效地管理和控制线程的执行。本文将深入探讨线程池的工作原理,以及如何使用Java的Executor框架来创建和管理线程池。我们将看到线程池如何提高性能,减少资源消耗,并提供更好的线程管理。
|
2天前
|
存储 安全 Java
Java并发编程中的高效数据结构:ConcurrentHashMap解析
【4月更文挑战第25天】在多线程环境下,高效的数据访问和管理是至关重要的。Java提供了多种并发集合来处理这种情境,其中ConcurrentHashMap是最广泛使用的一个。本文将深入分析ConcurrentHashMap的内部工作原理、性能特点以及它如何在保证线程安全的同时提供高并发性,最后将展示其在实际开发中的应用示例。
|
3天前
|
Java API 调度
[Java并发基础]多进程编程
[Java并发基础]多进程编程
|
3天前
|
Java API 调度
[AIGC] 深入理解Java并发编程:从入门到进阶
[AIGC] 深入理解Java并发编程:从入门到进阶
|
3天前
|
前端开发 Java 测试技术
Java从入门到精通:4.1.1参与实际项目,锻炼编程与问题解决能力
Java从入门到精通:4.1.1参与实际项目,锻炼编程与问题解决能力
|
3天前
|
SQL Java 数据库连接
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
|
3天前
|
SQL Java 数据库连接
Java从入门到精通:2.3.1数据库编程——学习JDBC技术,掌握Java与数据库的交互
ava从入门到精通:2.3.1数据库编程——学习JDBC技术,掌握Java与数据库的交互
|
3天前
|
IDE Java 开发工具
Java从入门到精通:1.3.1实践编程巩固基础知识
Java从入门到精通:1.3.1实践编程巩固基础知识
|
8天前
|
IDE Java 物联网
《Java 简易速速上手小册》第1章:Java 编程基础(2024 最新版)
《Java 简易速速上手小册》第1章:Java 编程基础(2024 最新版)
13 0
|
8天前
|
安全 Java 开发者
Java并发编程:深入理解Synchronized关键字
【4月更文挑战第19天】 在Java多线程编程中,为了确保数据的一致性和线程安全,我们经常需要使用到同步机制。其中,`synchronized`关键字是最为常见的一种方式,它能够保证在同一时刻只有一个线程可以访问某个对象的特定代码段。本文将深入探讨`synchronized`关键字的原理、用法以及性能影响,并通过具体示例来展示如何在Java程序中有效地应用这一技术。