Java多线程用法的实例详解
简介
Java 中的多线程技术能够让程序在同时执行多个任务的同时提高效率,因为它能够让多个任务之间并行地执行。本文将介绍 Java 多线程的用法并举例说明其使用方法。
线程的创建和执行
创建线程
Java 中有两种方式创建线程:
1. 继承 Thread 类并重写 run() 方法。
2. 实现 Runnable 接口并实现 run() 方法。
/*
* 继承 Thread 类
*/
class MyThread extends Thread {
public void run() {
System.out.println("Thread " + Thread.currentThread().getId() + " is running.");
}
}
/*
* 实现 Runnable 接口
*/
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread " + Thread.currentThread().getId() + " is running.");
}
}
启动线程
创建一个线程后,需要调用 start() 方法来启动线程。
MyThread t1 = new MyThread();
t1.start();
Thread t2 = new Thread(new MyRunnable());
t2.start();
等待线程结束
在某些情况下,我们需要主线程等待子线程结束后再执行下一步操作。可以使用 join() 方法来实现。
MyThread t1 = new MyThread();
t1.start();
t1.join();
Thread t2 = new Thread(new MyRunnable());
t2.start();
t2.join();
线程的生命周期
一个线程从创建到结束会经过以下 6 种状态:
- 新建状态(New):当一个线程对象被创建时,它处于新建状态。
- 就绪状态(Runnable):当调用线程的 start() 方法后,线程进入就绪状态。就绪状态的线程不一定会立即执行,因为还需要等待系统分配资源。
- 运行状态(Running):当线程获得系统资源后,开始执行 run() 方法,进入运行状态。
- 阻塞状态(Blocked):当线程在该状态下,它暂时停止执行。直到如下情况之一发生后,线程重新进入就绪状态:等待阻塞、同步阻塞和其他阻塞。
- 等待状态(Waiting):当线程等待特定的通知或事件发生时,进入等待状态。
- 结束状态(Terminated):当线程的 run() 方法完成或因异常而终止时,线程进入结束状态。
示例一:生产者和消费者
生产者和消费者模式是多线程并发编程中比较经典的一个例子。
class SharedResource {
private int data;
private boolean available = false;
synchronized void setData(int data) {
while (available) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
this.data = data;
available = true;
notifyAll();
System.out.println("Produced: " + data);
}
synchronized int getData() {
while (!available) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
available = false;
notifyAll();
System.out.println("Consumed: " + data);
return data;
}
}
class Producer implements Runnable {
private final SharedResource resource;
Producer(SharedResource resource) {
this.resource = resource;
}
public void run() {
int i = 0;
while (i < 10) {
resource.setData(i++);
}
}
}
class Consumer implements Runnable {
private final SharedResource resource;
Consumer(SharedResource resource) {
this.resource = resource;
}
public void run() {
int i = 0;
while (i < 10) {
resource.getData();
i++;
}
}
}
上述代码中,Producer 和 Consumer 分别实现了 Runnable 接口,它们共享的资源是一个名为 SharedResource 的类。其中 setData() 方法用于生产数据,getData() 方法用于消费数据。
在主线程中,创建 2 个线程,分别是生产者和消费者,分别启动这两个线程并等待它们完成。
public static void main(String[] args) throws InterruptedException {
SharedResource resource = new SharedResource();
Thread producerThread = new Thread(new Producer(resource));
Thread consumerThread = new Thread(new Consumer(resource));
producerThread.start();
consumerThread.start();
producerThread.join();
consumerThread.join();
}
示例二:线程池
当并发执行多个任务时,每个任务都需要创建一个新线程可能会导致系统开销过大。Java 提供线程池用于管理线程,其主要思想是在应用程序启动时创建线程池,线程池中保存多个等待执行的线程。需要执行任务时,可以从线程池中获取一个线程来执行任务,任务执行完毕后,线程归还给线程池。下面是一个线程池的示例:
public class ThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
int threadCount = 5;
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
for (int i = 0; i < threadCount; i++) {
executorService.execute(new Task(i));
}
executorService.shutdown();
while (!executorService.isTerminated()) {
Thread.sleep(1000);
}
System.out.println("All threads have finished executing.");
}
static class Task implements Runnable {
private final int taskId;
Task(int taskId) {
this.taskId = taskId;
}
public void run() {
System.out.println("Task " + taskId + " is running.");
try {
Thread.sleep(2000); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskId + " has finished.");
}
}
}
上述代码中,我们创建了一个固定大小为 5 的线程池,然后创建了 5 个任务并提交到线程池中执行。在所有任务执行完毕后,我们打印出一条消息表示所有线程都已经执行完成。
总结
本文介绍了 Java 多线程的用法,并举例说明了线程的创建、线程状态、等待线程结束、生产者和消费者、以及线程池等多个方面的内容。在实际项目中,合理地使用多线程技术能够提高程序的执行效率,但也需要注意线程安全和耗时操作等问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程用法的实例详解 - Python技术站