赞
踩
在此之前,我们先要明白什么是并发?为什么要并发编程?
在计算机中,同一时刻,只能有一条指令,在一个CPU上执行 后面的指令必须等到前面指令执行完才能执行,就是串行。在早年CPU核心数还少的时候倒是没什么。但是现如今,CPU性能(核心数和频率)已经不同往昔,为了充分利用CPU性能,我们引入并发。就好比银行只有5个窗口,有5个人要办事,就可以一起处理,第六个人到来才需要排队。
在 Java 中进行并发编程可以利用语言和库提供的特性,如线程、线程池、同步机制等。Java 为并发编程提供了许多有用的工具和库,包括基本的 Thread
类、并发集合、锁、条件变量等。在 Java 7 及以上版本中,java.util.concurrent
包还提供了更高层次的并发编程工具,包括线程池、并发队列、异步任务(Future
和 CompletableFuture
)等。
Thread
类:Java 提供了 Thread
类来创建和管理线程。你可以通过继承 Thread
类或实现 Runnable
接口来定义线程。public class MyThread extends Thread {
@Override
public void run() {
// 在这个方法中定义线程要执行的任务
System.out.println("Thread is running");
}
public static void main(String[] args) {
// 创建 MyThread 类的实例
MyThread myThread = new MyThread();
// 启动线程
myThread.start();
}
}
Runnable
接口:通过实现 Runnable
接口,并将其传递给 Thread
类的构造函数,来定义线程的执行逻辑。public class MyRunnable implements Runnable { @Override public void run() { // 在这个方法中定义线程要执行的任务 System.out.println("Runnable is running"); } public static void main(String[] args) { // 创建 MyRunnable 类的实例 MyRunnable myRunnable = new MyRunnable(); // 将 Runnable 对象传递给 Thread 构造函数 Thread thread = new Thread(myRunnable); // 启动线程 thread.start(); } }
synchronized
关键字:用于在方法或代码块上加锁,确保在同一时间只有一个线程可以执行受保护的代码。Lock
接口:提供了 synchronized
的替代方法,更灵活的锁定机制。ReadWriteLock
:提供了读写锁,用于优化读多写少的场景。ExecutorService
:用于管理线程池,可以通过 Executors
类提供的方法来创建不同类型的线程池。ScheduledExecutorService
:用于安排定时或周期性的任务执行。import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class ConcurrencyDemo { public static void main(String[] args) { // 创建一个固定大小的线程池 ExecutorService executor = Executors.newFixedThreadPool(3); // 提交任务给线程池 Future<?> future1 = executor.submit(() -> { System.out.println("任务 1 开始"); // 执行任务逻辑 System.out.println("任务 1 结束"); }); Future<?> future2 = executor.submit(() -> { System.out.println("任务 2 开始"); // 执行任务逻辑 System.out.println("任务 2 结束"); }); // 等待任务执行完成 try { future1.get(); // 阻塞直到任务 1 完成 future2.get(); // 阻塞直到任务 2 完成 } catch (Exception e) { e.printStackTrace(); } // 关闭线程池 executor.shutdown(); } }
创建了一个固定大小为 3 的线程池,然后提交了两个任务,并等待它们执行完毕。最后关闭线程池。
java.util.concurrent
包中的并发集合:例如 ConcurrentHashMap
、CopyOnWriteArrayList
、ConcurrentLinkedQueue
等,适合在多线程环境下使用。Future
接口:代表异步计算的结果。可以通过 ExecutorService
提供的方法提交任务,得到 Future
对象。CompletableFuture
类:更高级的异步任务工具,提供链式回调、组合和异常处理等功能。CountDownLatch
:用于线程同步,让线程等待直到某些操作完成。CyclicBarrier
:一个同步点,允许多个线程等待彼此到达一个状态。Semaphore
:用于控制资源的访问数量。Go 语言以其强大的并发编程特性而闻名。Go 语言提供了一些基本概念和机制来处理并发,包括 goroutines、channels 和 select 语句。这些工具使得 Go 在处理并发任务时非常高效且易于编写。
go
关键字,可以在后台启动一个新的 goroutine 来执行任务。package main
import (
"fmt"
)
func sayHello() {
fmt.Println("Hello!")
}
func main() {
go sayHello() // 启动一个新的 goroutine 执行 sayHello 函数
fmt.Println("Main goroutine")
}
make
函数创建 channels,并通过 <-
运算符发送和接收数据。package main import ( "fmt" ) func producer(ch chan int) { for i := 0; i < 5; i++ { ch <- i // 发送数据到 channel fmt.Printf("Produced: %d\n", i) } close(ch) // 关闭 channel } func consumer(ch chan int) { for value := range ch { // 从 channel 接收数据 fmt.Printf("Consumed: %d\n", value) } } func main() { ch := make(chan int) // 创建一个整型 channel go producer(ch) // 启动生产者 goroutine go consumer(ch) // 启动消费者 goroutine // 让主程序等待 goroutine 结束 // 可以使用 time.Sleep() 或 wait group 来实现 }
select
语句用于在多个 channel 上等待,并选择其中一个准备好的 channel 进行通信。select
语句类似于 switch
语句,但它是针对 channels 的。package main import ( "fmt" "time" ) func main() { ch1 := make(chan int) ch2 := make(chan int) go func() { time.Sleep(2 * time.Second) ch1 <- 1 }() go func() { time.Sleep(1 * time.Second) ch2 <- 2 }() select { case value := <-ch1: fmt.Printf("Received %d from ch1\n", value) case value := <-ch2: fmt.Printf("Received %d from ch2\n", value) } }
select
语句等待两个 channel 之一发送数据,然后接收数据并执行相应的分支。
这些是 Go 语言中并发编程的基本概念和用法。通过组合这些特性,Go 语言可以处理复杂的并发任务。
Java 21 中引入了 虚拟线程(Virtual Threads) ,它是一种新的线程实现,旨在提高并发应用程序的性能和可扩展性。虚拟线程与传统线程不同,它们是一种轻量级的线程实现,可以在 Java 虚拟机(JVM)上更有效地处理大量并发任务。
以下是虚拟线程的主要特点和优势:
Thread
、ExecutorService
等,只需将其替换为虚拟线程的实现即可。使用虚拟线程非常简单,只需在 Thread
类的实例化中指定 Thread.ofVirtual()
作为工厂方法即可:
public class VirtualThreadExample { public static void main(String[] args) { Runnable task = () -> { System.out.println("Virtual thread is running"); }; // 创建一个虚拟线程 Thread virtualThread = Thread.ofVirtual().start(task); // 等待虚拟线程执行完毕 try { virtualThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } }
我们使用 Thread.ofVirtual()
创建了一个虚拟线程,并启动它来执行指定的任务。与传统线程的使用类似,但虚拟线程在性能和资源效率方面有更大的优势。
虚拟线程是 Java 21 的一个重要特性,为开发者提供了处理大量并发任务的强大工具。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。