Java 并发性和多线程3

java 内存模型volatile实现与CPU缓存 CPU缓存架构        如下图所示是Intel的Skylake的CPU架构,我们可以看到缓存被分为L1、L2、L3这3层,CPU在运行中首先使用自己的寄存器,然后使用速度更快的L1缓存,其中:L1D缓存数据;L1I缓存指令;L1缓存和次快的L2同步数据;L2缓存和L3缓存同步数据(这里L2和L3按照内核数量做了等分,分给各个内核使用),我们可以简单地认为L3和内存同步数据。   CPU... 阅读详情

七、线程安全及不可变性

当多个线程同时访问同一个资源,并且其中的一个或者多个线程对这个资源进行了写操作,才会产生竞态条件。多个线程同时读同一个资源不会产生竞态条件。

我们可以通过创建不可变的共享对象来保证对象在线程间共享时不会被修改,从而实现线程安全。如下示例:

public class ImmutableValue{
    private int value = 0;

    public ImmutableValue(int value){
        this.value = value;
    }

    public int getValue(){
        return this.value;
    }
}

请注意 ImmutableValue 类的成员变量 value 是通过构造函数赋值的,并且在类中没有 set 方法。这意味着一旦 ImmutableValue 实例被创建,value 变量就不能再被修改,这就是不可变性。但你可以通过 getValue()方法读取这个变量的值。

(译者注:注意,“不变”(Immutable)和“只读”(Read Only)是不同的。当一个变量是“只读”时,变量的值不能直接改变,但是可以在其它变量发生改变的时候发生改变。比如,一个人的出生年月日是“不变”属性,而一个人的年龄便是“只读”属性,但是不是“不变”属性。随着时间的变化,一个人的年龄会随之发生变化,而一个人的出生年月日则不会变化。这就是“不变”和“只读”的区别。(摘自《Java 与模式》第 34 章))

如果你需要对 ImmutableValue 类的实例进行操作,可以通过得到 value 变量后创建一个新的实例来实现,下面是一个对 value 变量进行加法操作的示例:

public class ImmutableValue{
    private int value = 0;

    public ImmutableValue(int value){
        this.value = value;
    }

    public int getValue(){
        return this.value;
    }

    public ImmutableValue add(int valueToAdd){
        return new ImmutableValue(this.value + valueToAdd);
    }
}

请注意 add()方法以加法操作的结果作为一个新的 ImmutableValue 类实例返回,而不是直接对它自己的 value 变量进行操作。

## 引用不是线程安全的!

重要的是要记住,即使一个对象是线程安全的不可变对象,指向这个对象的引用也可能不是线程安全的。看这个例子:

public void Calculator{
    private ImmutableValue currentValue = null;

    public ImmutableValue getValue(){
        return currentValue;
    }

    public void setValue(ImmutableValue newValue){
        this.currentValue = newValue;
    }

    public void add(int newValue){
        this.currentValue = this.currentValue.add(newValue);
    }
}

Calculator 类持有一个指向 ImmutableValue 实例的引用。注意,通过 setValue()方法和 add()方法可能会改变这个引用。因此,即使 Calculator 类内部使用了一个不可变对象,但 Calculator 类本身还是可变的,因此 Calculator 类不是线程安全的。换句话说:ImmutableValue 类是线程安全的,但使用它的类不是。当尝试通过不可变性去获得线程安全时,这点是需要牢记的。

要使 Calculator 类实现线程安全,将 getValue()、setValue()和 add()方法都声明为同步方法即可。

八、Java 内存模型

Java 内存模型把 Java 虚拟机内部划分为线程栈和堆。

堆和栈的知识补漏:

Java把内存分成两种,一种叫做栈内存,一种叫做堆内存

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。

堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。

引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针! 

具体文章参见:Java中的堆和栈的区别

这张图演示了 Java 内存模型的逻辑视图。

每一个运行在 Java 虚拟机里的线程都拥有自己的线程栈。这个线程栈包含了这个线程调用的方法当前执行点相关的信息。一个线程仅能访问自己的线程栈。一个线程创建的本地变量对其它线程不可见,仅自己可见。即使两个线程执行同样的代码,这两个线程任然在在自己的线程栈中的代码来创建本地变量。因此,每个线程拥有每个本地变量的独有版本。

所有原始类型的本地变量都存放在线程栈上,因此对其它线程不可见。一个线程可能向另一个线程传递一个原始类型变量的拷贝,但是它不能共享这个原始类型变量自身。

堆上包含在 Java 程序中创建的所有对象,无论是哪一个对象创建的。这包括原始类型的对象版本。如果一个对象被创建然后赋值给一个局部变量,或者用来作为另一个对象的成员变量,这个对象任然是存放在堆上。

下面这张图演示了调用栈和本地变量存放在线程栈上,对象存放在堆上。

九、Java同步块

Java 同步块(synchronized block)用来标记方法或者代码块是同步的。Java 同步块用来避免竞争。本文介绍以下内容:

  • Java 同步关键字(synchronzied)
  • 实例方法同步
  • 静态方法同步
  • 实例方法中同步块
  • 静态方法中同步块
  • Java 同步示例

## Java 同步关键字(synchronized)

Java 中的同步块用 synchronized 标记。同步块在 Java 中是同步在某个对象上。所有同步在一个对象上的同步块在同时只能被一个线程进入并执行操作。所有其他等待进入该同步块的线程将被阻塞,直到执行该同步块中的线程退出。

有四种不同的同步块:

  1. 实例方法
  2. 静态方法
  3. 实例方法中的同步块
  4. 静态方法中的同步块

上述同步块都同步在不同对象上。实际需要那种同步块视具体情况而定。

### 实例方法同步

下面是一个同步的实例方法:

 public synchronized void add(int value){
this.count += value;
 }

注意在方法声明中同步(synchronized )关键字。这告诉 Java 该方法是同步的。

Java 实例方法同步是同步在拥有该方法的对象上。这样,每个实例其方法同步都同步在不同的对象上,即该方法所属的实例。只有一个线程能够在实例方法同步块中运行。如果有多个实例存在,那么一个线程一次可以在一个实例同步块中执行操作。一个实例一个线程。

### 静态方法同步 

静态方法同步和实例方法同步方法一样,也使用 synchronized 关键字。Java 静态方法同步如下示例:

public static synchronized void add(int value){
 count += value;
 }

同样,这里 synchronized 关键字告诉 Java 这个方法是同步的。

静态方法的同步是指同步在该方法所在的类对象上。因为在 Java 虚拟机中一个类只能对应一个类对象,所以同时只允许一个线程执行同一个类中的静态同步方法。

对于不同类中的静态同步方法,一个线程可以执行每个类中的静态同步方法而无需等待。不管类中的那个静态同步方法被调用,一个类只能由一个线程同时执行。

### 实例方法中的同步块 

有时你不需要同步整个方法,而是同步方法中的一部分。Java 可以对方法的一部分进行同步。

在非同步的 Java 方法中的同步块的例子如下所示:

复制代码

public void add(int value){

    synchronized(this){
       this.count += value;
    }
  }

复制代码

示例使用 Java 同步块构造器来标记一块代码是同步的。该代码在执行时和同步方法一样。

注意 Java 同步块构造器用括号将对象括起来。在上例中,使用了“this”,即为调用 add 方法的实例本身。在同步构造器中用括号括起来的对象叫做监视器对象。上述代码使用监视器对象同步,同步实例方法使用调用方法本身的实例作为监视器对象。

一次只有一个线程能够在同步于同一个监视器对象的 Java 方法内执行。

下面两个例子都同步他们所调用的实例对象上,因此他们在同步的执行效果上是等效的。

复制代码

 public class MyClass {

    public synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

    public void log2(String msg1, String msg2){
       synchronized(this){
          log.writeln(msg1);
          log.writeln(msg2);
       }
    }
  }

复制代码

在上例中,每次只有一个线程能够在两个同步块中任意一个方法内执行。

如果第二个同步块不是同步在 this 实例对象上,那么两个方法可以被线程同时执行。

### 静态方法中的同步块 

和上面类似,下面是两个静态方法同步的例子。这些方法同步在该方法所属的类对象上。

复制代码

public class MyClass {
    public static synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
          log.writeln(msg1);
          log.writeln(msg2);
       }
    }
  }

复制代码

这两个方法不允许同时被线程访问。

如果第二个同步块不是同步在 MyClass.class 这个对象上。那么这两个方法可以同时被线程访问。

## Java同步实例

在下面例子中,启动了两个线程,都调用 Counter 类同一个实例的 add 方法。因为同步在该方法所属的实例上,所以同时只能有一个线程访问该方法。

复制代码

public class Counter{
     long count = 0;

     public synchronized void add(long value){
       this.count += value;
     }
  }
  public class CounterThread extends Thread{

     protected Counter counter = null;

     public CounterThread(Counter counter){
        this.counter = counter;
     }

     public void run() {
    for(int i=0; i<10; i++){
           counter.add(i);
        }
     }
  }
  public class Example {

    public static void main(String[] args){
      Counter counter = new Counter();
      Thread  threadA = new CounterThread(counter);
      Thread  threadB = new CounterThread(counter);

      threadA.start();
      threadB.start();
    }
  }

复制代码

创建了两个线程。他们的构造器引用同一个 Counter 实例。Counter.add 方法是同步在实例上,是因为 add 方法是实例方法并且被标记上 synchronized 关键字。因此每次只允许一个线程调用该方法。另外一个线程必须要等到第一个线程退出 add()方法时,才能继续执行方法。

如果两个线程引用了两个不同的 Counter 实例,那么他们可以同时调用 add()方法。这些方法调用了不同的对象,因此这些方法也就同步在不同的对象上。这些方法调用将不会被阻塞。如下面这个例子所示:

复制代码

public class Example {

    public static void main(String[] args){
      Counter counterA = new Counter();
      Counter counterB = new Counter();
      Thread  threadA = new CounterThread(counterA);
      Thread  threadB = new CounterThread(counterB);

      threadA.start();
      threadB.start();
    }
  }

复制代码

注意这两个线程,threadA 和 threadB,不再引用同一个 counter 实例。CounterA 和 counterB 的 add 方法同步在他们所属的对象上。调用 counterA 的 add 方法将不会阻塞调用 counterB 的 add 方法。

回到顶部

十、线程通信

线程通信的目标是使线程间能够互相发送信号。另一方面,线程通信使线程能够等待其他线程的信号。

例如,线程 B 可以等待线程 A 的一个信号,这个信号会通知线程 B 数据已经准备好了。本文将讲解以下几个 JAVA 线程间通信的主题:

  1. 通过共享对象通信
  2. 忙等待
  3. wait(),notify()和 notifyAll()
  4. 丢失的信号
  5. 假唤醒
  6. 多线程等待相同信号
  7. 不要对常量字符串或全局对象调用 wait()

文章地址:极客企业版 

回到顶部

十一、死锁

死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候。

例如,如果线程 1 锁住了 A,然后尝试对 B 进行加锁,同时线程 2 已经锁住了 B,接着尝试对 A 进行加锁,这时死锁就发生了。线程 1 永远得不到 B,线程 2 也永远得不到 A,并且它们永远也不会知道发生了这样的事情。为了得到彼此的对象(A 和 B),它们将永远阻塞下去。这种情况就是一个死锁。

文章地址:极客企业版

回到顶部

十二、避免死锁

在有些情况下死锁是可以避免的。本文将展示三种用于避免死锁的技术:

  1. 加锁顺序
  2. 加锁时限
  3. 死锁检测

## 加锁顺序

当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。

如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。看下面这个例子:

复制代码

Thread 1:
  lock A 
  lock B

Thread 2:
   wait for A
   lock C (when A locked)

Thread 3:
   wait for A
   wait for B
   wait for C

如果一个线程(比如线程 3)需要一些锁,那么它必须按照确定的顺序获取锁。它只有获得了从顺序上排在前面的锁之后,才能获取后面的锁。

例如,线程 2 和线程 3 只有在获取了锁 A 之后才能尝试获取锁 C(译者注:获取锁 A 是获取锁 C 的必要条件)。因为线程 1 已经拥有了锁 A,所以线程 2 和 3 需要一直等到锁 A 被释放。然后在它们尝试对 B 或 C 加锁之前,必须成功地对 A 加了锁。

按照顺序加锁是一种有效的死锁预防机制。但是,这种方式需要你事先知道所有可能会用到的锁(译者注:并对这些锁做适当的排序),但总有些时候是无法预知的。

JAVA编程【多线程编程】 线程创建:可以通过继承 Thread 类或者实现 Runnable 接口来创建线程。线程同步:可以通过 synchronized 关键字或者 ReentrantLock 来确保线程安全。线程池:通过 ExecutorService 来管理线程池,提高性能。 阅读详情

相关推荐

Allegro规则管理器实战:5步搞定Xnet等长组设置(含Relative Propagation Delay配置)

本文详细介绍了在Cadence Allegro规则管理器中,通过5个实战步骤高效设置Xnet等长组的方法。核心内容包括创建Xnet属性、定义引脚对、建立匹配组,并重点讲解了Relative Propagation Delay规则的配置与应用,帮助PCB设计师确保高速信号时序对齐,提升系统稳定性与性能。

weixin_29193259的博客 518

3、Java并发性和多线程-多线程的代价

以下内容转自http://ifeve.com/costs-of-multithreading/: 从一个单线程的应用到一个多线程的应用并不仅仅带来好处,它也会有一些代价。不要仅仅为了使用多线程而使用多线程。而应该明确在使用多线程时能多来的好处比所付出的代价大的时候,才使用多线程。如果存在疑问,应该尝试测量一下应用程序的性能和响应能力,而不只是猜测。 设计更复杂 虽然有一些多线程应用程...

weixin_34234721的博客 86

F5 Shape盾JSVMP核心检测点与无限并发Header生成实战(TikTok/航司)

本文深入剖析了F5 Shape盾结合JSVMP技术的核心风控机制,详细解读了其针对浏览器指纹、行为时序等多维度的检测逻辑。通过实战案例,分享了如何通过逆向分析、精准Hook关键检测点,并构建稳定、高并发的请求Header生成方案,以应对TikTok、航司等平台的高级反爬挑战。

weixin_29325007的博客 1014

多线程&并发篇(1024节日快乐)

再次渡入繁世,人潮汹涌,眼里茫然,信仰永恒,皆为华夏。

退役复学在校大学生,目光所至,皆为华夏 5952

uniapp [安卓苹果App端] - 实现支付宝支付功能+拉起支付宝app付款支付后返回跳转到原页面,详解uniApp如何唤起本机支付宝并跳转到支付页面全流程及示例源码(APP端支付宝支付,支持打包

全网最详细的uniapp支付宝支付教程,uniapp支付宝支付流程,uni-app项目在APP端使用支付宝支付功能,uniapp前端实现支付宝支付,uniapp中唤醒支付宝进行支付并返回app,uniApp调起支付宝支付失败报错,uniapp app端调支付宝支付接口,uniapp开发安卓App对接支付宝支付,uniapp苹果ios唤起支付宝支付,uniapp调用支付宝支付uniapp开发app-调用支付宝支付,uniapp开发安卓苹果app如何接入支付宝支付,UniApp中实现支付宝支付功能,支付报错,调

🏆 前端领域优质创作者 1万+

手把手教你学GPU的KMD专栏--3.1 设备初始化流程深度解析

本文深入解析了KMD(内核模式驱动)设备初始化流程,这是GPU驱动开发最基础且关键的环节。初始化流程包括6个核心阶段:KMD模块加载、PCIe设备探测匹配、GPU硬件初始化、显存分配映射、中断系统配置和设备注册。每个阶段都有详细步骤解析,涉及关键数据结构和错误处理机制。文章还分析了常见问题(驱动加载失败、显存分配失败、中断配置失败)的解决方案,并指出未来趋势将向动态初始化、安全增强和AI优化方向发展。正确高效的初始化流程是确保GPU被操作系统安全使用的前提,也是后续内存管理、任务调度等功能的基础。

MHD0815的博客 262

java 异步服务调用_java异步调用方法

一.利用多线程直接new线程Thread t = newThread(){@Overridepublic voidrun() {longTimeMethod();}};使用线程池private ExecutorService executor =Executors.newCachedThreadPool() ;public void fun() throwsException {executor....

weixin_33444829的博客 1274

轨道平面系与轨道姿态系

文章摘要: 轨道平面系与轨道姿态系是航天任务中两个核心坐标系。轨道平面系(惯性系)以地心为原点,Z轴沿轨道角动量方向,用于轨道确定和机动规划;轨道姿态系(如LVLH系)以航天器质心为原点,Z轴指向地心,用于姿态控制和对地观测。两者通过旋转矩阵相互转换:轨道平面系基于轨道根数构建,保持静态;而LVLH系随轨道运动连续旋转。前者适用于全局轨道分析,后者支撑局部任务执行。理解二者的定义差异(原点、基准轴、惯性属性)及数学转换关系,对航天器姿态轨道控制系统的设计与操作至关重要。

ScilogyHunter的博客 88

JAVA中的伪共享与缓存行

JAVA中的伪共享与缓存行

qq_45443475的博客 1870

杰理AC696N使用ADC检测电位器调音量教程

本教程详细介绍了在杰理AC696N芯片上使用ADC功能检测电位器电压值的方法。主要内容包括:硬件连接方式(电位器VCC/OUT/GND分别接3.3V、PA3引脚和地线),10位ADC配置(0-1023对应0-3.3V),以及核心代码实现。关键步骤涉及ADC采样通道初始化、GPIO引脚配置(关闭数字输入和上下拉电阻),以及通过定时器实现50Hz采样频率。教程还详解了ADC值到系统音量的线性映射算法,并提供了完整的代码示例和调试方法,帮助开发者实现电位器实时控制音量的功能。

qq_42014563的博客 1246

【SCADA】KingSCADA将数据插入SQLServer的方法

1、创建数据库及数据表格;2、配置ODBC数据源。3、通过KingSCADA与数据库建立连接,将数据写入数据库对应表格。

做有价值的事,积累有价值的笔记! 4961

【Java系列】深入解析Java多线程

Java多线程是提高程序并发性和响应能力的重要手段,需要掌握多线程的实现方式、同步机制、线程之间的通信机制等,以确保多线程程序的正确性和稳定性。

颜淡慕潇 2万+

基于STM32、HAL库的 CH9102X USB转UART收发器 驱动程序设计

/ 或 UART_HWCONTROL_RTS_CTS。// 其他函数实现类似,使用HAL_UART_Transmit_IT, HAL_UART_Receive_IT等。UART_TXD <---> USARTx_RX (STM32接收)UART_RXD <---> USARTx_TX (STM32发送)* @param huart: UART句柄指针。* @param huart: UART句柄指针。* @param huart: UART句柄指针。* @param huart: UART句柄指针。

corlin6688的博客 506

Java的多线程和并发性

多线程: 多线程是在同一个程序内部并行执行,因此会对相同的内存空间进行并发读写操作 并发性: 计算机能在同一时间点并行执行多任务或多进程。虽然并不是真正意义上的“同一时间点”,而是多个任务或进程共享一个CPU,并交由操作系统来完成多任务间对CPU的运行切换,以使得每个任务都有机会获得一定的时间片运行。 并发模型与分布式系统的相似性: 在并发系统中线程之间可以相互通信。在分布式系统中进程之间也可以相互通信(进程有可能在不同的机器中)。线程和进程之间具有很多相似的特性。这也就是为什么很多并发模型通常类

weixin_45821196的博客 572

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

JAVA多线程和并发性知识点总结

上次我总结了一份JAVA 面向对象和集合知识点总结: http://blog.youkuaiyun.com/zhoubin1992/article/details/46481759 这次对JAVA多线程和并发性相关知识点进行总结,方便各位博友学习以及自己复习之用。一、 什么是进程、线程?线程和进程的区别?1. 进程 当一个程序进入内存运行时,即变成一个进程。进程是处于运行过程中的程序。 进程是操作系统进

牧之 1984

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Java并发性和多线程的介绍与分析

在过去单CPU时代,单任务在一个时间点只能执行单一程序。之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程。虽然并不是真正意义上的“同一时间点”,而是多个任务或进程共享一个CPU,并交由操作系统来完成多任务间对CPU的运行切换,以使得每个任务都有机会获得一定的时间片运行。 一、多线程的发展由来 随着多任务对软件开发者带来的新挑战,程序不在能假设独占所有的CPU时间、所有的内存和其他计算机资源。一个好的程序榜样是在其不再使用这些资源时对其进行释放,以使得其他程序能有机会使用这些资源。 再后来发展

猿小许的博客 193

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【Java多线程】9 Java 的并发性能优化

通过合理的设计和有效的策略,我们可以优化并发程序的性能,提高系统的响应速度和吞吐量。理解并应用这些优化技巧,将使我们能够更高效地编写高性能的并发应用。通过合理的设计和有效的策略,我们可以提高系统的响应速度和吞吐量。以下是一些常用的并发性能优化技巧。锁的粒度指的是被锁住的代码范围。较小的锁粒度可以减少锁争用,提高并发性能。在多线程设计中,选择合适的线程模型能够提高系统性能。持有锁的时间越短,竞争的机会越小,因此减少锁的持有时间是优化的关键。,总结一些在实际开发中应遵循的最佳实践和建议。

A1924的博客 1051

Java高级教程:Java并发性和多线程

Java并发性和多线程: (中文,属于人工翻译,高质量):http://ifeve.com/java-concurrency-thread-directory/ (英文):http://tutorials.jenkov.com/java-concurrency/index.html 总结: 1、我的实践笔记:http://www.cnblogs.co...

weixin_34273046的博客 76

java线程并发解决_[Java基础]多线程之并发性以及解决方法

首先演示一下并发性(关于并发性的解释建议看MSDN中.net部分相关的解释、感觉微软解释的很详细、不仅说了并发性 还有其他可能由多线程引发其他问题)1 public class ThreadDemo2 {2 public static void main(String[] args) {3 TestThread1 thread = new TestThread1();4 ...

weixin_30025473的博客 172

Java:多线程和JUC详解

Java多线程和JUC详解

游手好闲 3713

Java多线程及通信方式详解

在讨论这个问题之前,首先要知道什么是Java多线程,我们拿个生活中的例子来说,例如在手机上使用软件,你可以同时运行多个应用程序或功能。你可以同时打开浏览器、音乐播放器和社交媒体应用。每个应用程序都在后台独立运行,就像多线程能够同时执行多个任务一样。但是有时候你需要等待某些操作完成才能继续进行。比如当你在等待一个应用加载数据时,你可以同时切换到另一个应用。但是直到数据加载完成,你才能够进行下一步操作。这种等待和切换类似于多线程中的线程间同步和等待操作。

EverythingAtOnce的博客 1789

Java多线程和并发性相关(个人学习总结)

一路走来,走过很多Java多线程的坑,以前一直习惯记于笔头;现从笔记搬于博客,从初识到深入,慢慢详记——持续更新。(目的仅为个人学习总结,所学所记;如有幸大佬看见,若能指点一二也是极好的。) Chapter1:多线程基础 一、多线程创建方式: 1.继承Thread类(Thread类实现了Runnable类),重写Run方法; 2.实现Runnable类,重写Run方法; 3.匿...

SilenceViking的充电桩 340
上一篇: Java 并发性和多线程2
ohmygodvv
博客等级 码龄4年 521粉丝 140原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ohmygodvv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值