Java多线程编程实战:10个经典练习题详解与代码实现
1. 创建两个线程分别打印“Hello”和“World”
背景
在多线程编程中,线程是程序执行的基本单位之一。通过创建多个线程,可以让程序同时执行多个任务。
实现思路
- 使用
Thread类创建两个线程。 - 每个线程分别打印“Hello”和“World”。
代码实现
public class ThreadExample1 {
public static void main(String[] args) {
Thread helloThread = new Thread(() -> {
System.out.println("Hello");
});
Thread worldThread = new Thread(() -> {
System.out.println("World");
});
helloThread.start();
worldThread.start();
}
}
输出示例
Hello
World
2. 使用Thread类实现线程的启动和停止
背景
Thread类是Java中用于创建线程的类。线程的启动通过调用start()方法实现,而线程的停止可以通过设置一个标志变量来实现。
实现思路
- 使用
Thread类创建一个线程。 - 在线程中通过一个标志变量控制线程的运行状态。
- 在主线程中通过设置标志变量来停止线程。
代码实现
public class ThreadExample2 {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
boolean running = true;
while (running) {
System.out.println("Thread is running...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
running = false;
}
}
System.out.println("Thread stopped.");
});
thread.start();
Thread.sleep(5000); // 主线程等待5秒后停止线程
thread.interrupt(); // 通过中断线程来停止线程
}
}
输出示例
Thread is running...
Thread is running...
Thread is running...
Thread stopped.
3. 使用Runnable接口实现线程
背景
Runnable接口是Java中用于实现多线程的接口。通过实现Runnable接口,可以将线程的逻辑封装到一个对象中,然后通过Thread类来运行。
实现思路
- 定义一个类实现
Runnable接口。 - 在
run()方法中实现线程的逻辑。 - 使用
Thread类来运行实现Runnable接口的对象。
代码实现
public class ThreadExample3 {
public static void main(String[] args) {
Runnable helloTask = () -> {
System.out.println("Hello from Runnable");
};
Runnable worldTask = () -> {
System.out.println("World from Runnable");
};
Thread helloThread = new Thread(helloTask);
Thread worldThread = new Thread(worldTask);
helloThread.start();
worldThread.start();
}
}
输出示例
Hello from Runnable
World from Runnable
4. 实现线程的同步,避免数据竞争
背景
在多线程环境中,多个线程可能会同时访问和修改共享资源,导致数据竞争和不一致的问题。通过线程同步机制可以避免这些问题。
实现思路
- 使用
synchronized关键字同步方法或代码块。 - 确保多个线程访问共享资源时,只有一个线程可以执行同步代码。
代码实现
public class ThreadExample4 {
private static int count = 0;
public static void main(String[] args) {
Runnable incrementTask = () -> {
for (int i = 0; i < 1000; i++) {
synchronized (ThreadExample4.class) {
count++;
}
}
};
Thread thread1 = new Thread(incrementTask);
Thread thread2 = new Thread(incrementTask);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final count: " + count);
}
}
输出示例
Final count: 2000
5. 使用join方法等待线程结束
背景
join方法用于等待一个线程结束。主线程调用某个线程的join方法后,主线程会等待该线程执行完成后再继续执行。
实现思路
- 创建一个线程并启动。
- 在主线程中调用该线程的
join方法,等待其结束。 - 主线程继续执行。
代码实现
public class ThreadExample5 {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
System.out.println("Thread is running...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread finished.");
});
thread.start();
thread.join(); // 主线程等待thread线程结束
System.out.println("Main thread continues...");
}
}
输出示例
Thread is running...
Thread finished.
Main thread continues...
6. 使用sleep方法暂停线程
背景
sleep方法用于暂停当前线程的执行,指定的时间内线程不会运行。
实现思路
- 在线程中调用
Thread.sleep()方法,暂停线程的执行。 - 指定暂停的时间(以毫秒为单位)。
代码实现
public class ThreadExample6 {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("Thread started...");
try {
Thread.sleep(2000); // 暂停2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread resumed...");
});
thread.start();
}
}
输出示例
Thread started...
(2秒后)
Thread resumed...
7. 使用volatile关键字确保线程间变量的可见性
背景
volatile关键字用于确保线程间变量的可见性。当一个变量被volatile修饰时,线程对变量的修改会立即写入主内存,其他线程可以立即看到变量的最新值。
实现思路
- 使用
volatile修饰一个变量。 - 在一个线程中修改该变量的值。
- 在另一个线程中读取该变量的值。
代码实现
public class ThreadExample7 {
private static volatile boolean running = true;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (running) {
System.out.println("Thread is running...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread stopped.");
});
thread.start();
Thread.sleep(5000); // 主线程等待5秒后停止线程
running = false; // 修改volatile变量的值
}
}
输出示例
Thread is running...
Thread is running...
Thread is running...
Thread stopped.
8. 使用synchronized块实现线程同步
背景
synchronized块用于同步代码块,确保多个线程访问共享资源时的线程安全。
实现思路
- 使用
synchronized块同步对共享资源的访问。 - 指定同步块的锁对象。
代码实现
public class ThreadExample8 {
private static int count = 0;
private static final Object lock = new Object();
public static void main(String[] args) {
Runnable incrementTask = () -> {
for (int i = 0; i < 1000; i++) {
synchronized (lock) {
count++;
}
}
};
Thread thread1 = new Thread(incrementTask);
Thread thread2 = new Thread(incrementTask);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final count: " + count);
}
}
输出示例
Final count: 2000
9. 使用ExecutorService管理线程池
背景
ExecutorService是Java中用于管理线程池的接口。通过线程池可以复用线程,提高线程的利用率。
实现思路
- 使用
Executors工具类创建一个线程池。 - 提交任务到线程池中执行。
- 关闭线程池。
代码实现
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadExample9 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(() -> {
System.out.println("Task 1 executed by " + Thread.currentThread().getName());
});
executorService.submit(() -> {
System.out.println("Task 2 executed by " + Thread.currentThread().getName());
});
executorService.shutdown(); // 关闭线程池
}
}
输出示例
Task 1 executed by pool-1-thread-1
Task 2 executed by pool-1-thread-2
10. 使用Callable和Future实现线程的返回值
背景
Callable接口用于定义有返回值的任务,Future接口用于获取任务的返回值。
实现思路
- 定义一个实现
Callable接口的任务。 - 提交任务到线程池中执行。
- 使用
Future获取任务的返回值。
代码实现
import java.util.concurrent.*;
public class ThreadExample10 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Callable<Integer> task = () -> {
System.out.println("Task is running...");
Thread.sleep(2000);
return 42; // 返回值
};
Future<Integer> future = executorService.submit(task);
System.out.println("Waiting for task to complete...");
Integer result = future.get(); // 获取任务的返回值
System.out.println("Task completed with result: " + result);
executorService.shutdown();
}
}
输出示例
Waiting for task to complete...
Task is running...
(2秒后)
Task completed with result: 42
浙公网安备 33010602011771号