当前仍在编辑文章 - 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() 给调度程序的提示,当前线程愿意让出它当前对处理器的使用
目录
相关文章
|
4天前
|
缓存 安全 Java
Java并发编程进阶:深入理解Java内存模型
Java并发编程进阶:深入理解Java内存模型
14 0
|
4天前
|
监控 Java 测试技术
Java并发编程最佳实践:设计高性能的多线程系统
Java并发编程最佳实践:设计高性能的多线程系统
18 1
|
2天前
|
安全 Java API
告别繁琐编码,拥抱Java 8新特性:Stream API与Optional类助你高效编程,成就卓越开发者!
【8月更文挑战第29天】Java 8为开发者引入了多项新特性,其中Stream API和Optional类尤其值得关注。Stream API对集合操作进行了高级抽象,支持声明式的数据处理,避免了显式循环代码的编写;而Optional类则作为非空值的容器,有效减少了空指针异常的风险。通过几个实战示例,我们展示了如何利用Stream API进行过滤与转换操作,以及如何借助Optional类安全地处理可能为null的数据,从而使代码更加简洁和健壮。
16 0
|
4天前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
Java并发编程实战:使用synchronized关键字实现线程安全
16 0
|
1天前
|
存储 安全 Java
【数据保护新纪元】Java编程:揭秘黑客攻击背后的防线,打造坚不可摧的安全堡垒!
【8月更文挑战第30天】本文全面介绍了Java安全性编程的基本概念和实战技巧,涵盖输入验证、错误处理、数据加密、权限控制及安全审计等方面。通过具体示例,帮助开发者有效预防安全风险,提升程序的稳定性和可靠性,保护用户数据安全。适合希望提升Java应用安全性的开发者参考。
13 4
|
1天前
|
IDE Java 测试技术
揭秘Java高效编程:测试与调试实战策略,让你代码质量飞跃,职场竞争力飙升!
【8月更文挑战第30天】在软件开发中,测试与调试对确保代码质量至关重要。本文通过对比单元测试、集成测试、调试技巧及静态代码分析,探讨了多种实用的Java测试与调试策略。JUnit和Mockito分别用于单元测试与集成测试,有助于提前发现错误并提高代码可维护性;Eclipse和IntelliJ IDEA内置调试器则能快速定位问题;Checkstyle和PMD等工具则通过静态代码分析发现潜在问题。综合运用这些策略,可显著提升代码质量,为项目成功打下坚实基础。
|
1天前
|
Java 开发者 UED
【揭秘Java编程新境界】事件驱动:如何在Java中捕捉每一个关键瞬间?
【8月更文挑战第30天】事件驱动编程是一种编程范式,使程序能在事件发生时响应,而非按严格顺序执行。本文介绍Java中的事件驱动编程,包括基本概念、优势及其实现方法。通过事件监听器和事件对象,Java能够高效处理GUI、网络编程和游戏开发中的各种事件。文中还提供了创建事件监听器、自定义事件及处理多个事件源的示例代码,帮助读者更好地理解和应用这一强大的编程范式。
|
3天前
|
Java 程序员 编译器
Java编程中的异常处理:理解与实践
【8月更文挑战第28天】在Java的世界中,异常是程序运行中不可避免的一部分。它们像是旅途中的路障,挑战着程序员的智慧和耐心。本文将带你走进Java的异常处理机制,从基础概念到高级应用,我们将一起探索如何优雅地处理这些不请自来的挑战者。你将学习到如何捕获、处理以及预防异常,确保你的代码像经验丰富的旅行者一样,即使在最崎岖的道路上也能从容前行。
|
4天前
|
Java 程序员 开发者
Java编程中的异常处理:从基础到进阶
【8月更文挑战第27天】在Java的世界中,异常处理是维护程序健壮性的关键。本文将带你从异常处理的基本概念出发,深入探讨如何优雅地管理错误和异常,确保你的代码不仅能够应对预料之外的情况,还能提供清晰的调试信息。我们将一起探索try-catch-finally语句的细节,了解如何自定义异常,以及最佳实践来优化你的异常处理策略。准备好了吗?让我们一起潜入Java异常处理的深海,揭开它的神秘面纱。
|
3天前
|
存储 Java
Java编程中的对象序列化与反序列化
【8月更文挑战第28天】在Java世界中,对象序列化与反序列化是数据持久化和网络传输的关键技术。本文将深入浅出地探讨这一过程,带你领略其背后的原理及应用,让你的程序在数据的海洋中自由航行。
下一篇
云函数