1 线程的基础概念
1.1 什么是线程?
定义:线程是程序执行的最小单元。一个进程可以包含多个线程,这些线程共享进程的内存空间,但他们可以独立执行。
线程与进程的区别:线程是进程的一个子集,进程是一个独立的运行环境,而线程是在进程内部执行的多个任务
1.2 示例代码
public class BasicThreadExample {
public static void main(String[] args) {
// 主线程
System.out.println("Main thread is running");
// 创建一个新线程
Thread thread = new Thread(() -> System.out.println("New thread is running"));
thread.start(); // 启动新线程
System.out.println("Main thread is finishing");
}
}
1.3 输出
Main thread is running
New thread is running
Main thread is finishing
解释:这里的 Thread
是一个独立的线程,它与主线程并行运行。
2 创建线程
2.1 方式一:继承 Thread
类
class MyThread extends Thread {
@Override
public void run() {
// 线程执行的代码
System.out.println("线程正在运行: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 启动线程
}
}
2.2 方式二:实现 Runnable
接口
class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的代码
System.out.println("线程正在运行: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start(); // 启动线程
}
}
3 管理线程的生命周期
线程的生命周期包括创建、运行、等待(sleep)、阻塞(block)、终止等。你可以使用 start()
方法启动线程,sleep()
方法让线程休眠一段时间,join()
方法等待线程完成。
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(() -> { //创建一个线程
try {
Thread.sleep(1000); // 线程休眠1秒
System.out.println("线程完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start(); // 启动线程
try {
thread.join(); // 等待线程结束
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程继续执行");
}
}
4 线程同步
当多个线程访问共享资源时,可能会发生数据不一致的问题。可以使用 synchronized
关键字来确保线程的同步。
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("计数器的值: " + counter.getCount());
}
}
5 使用线程池
如果需要创建和管理大量的线程,可以使用 ExecutorService
提供的线程池。
package com.czq.utils.test;
import com.czq.utils.PerformanceTester;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class test {
public void serveCustomer(){
ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个有3个线程的线程池
executor.submit(this::takeOrder);
executor.submit(this::cookFood);
executor.submit(this::serveFood);
executor.submit(this::billCustomer);
executor.shutdown(); // 关闭线程池,等待所有任务完成
// 等待所有任务完成
while (!executor.isTerminated()) {
// 可以执行一些其他的操作或仅仅等待
}
// if (executor.awaitTermination(60, TimeUnit.SECONDS)) {
// System.out.println("所有任务完成!");
// } else {
// System.out.println("仍有任务未完成!");
// }
// 60:表示你希望最多等待 60 个时间单位。在这里是 60 秒。
// TimeUnit.SECONDS:指定了时间单位为秒。TimeUnit 是一个枚举,提供了多种时间单位,如秒 (SECONDS)、毫秒 (MILLISECONDS)、分钟 (MINUTES) 等。
System.out.println("所有任务完成!");
}
private void takeOrder() {
try {
System.out.println("我已经开始工作啦 --- 点餐");
Thread.sleep(1000); // 模拟点餐时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("点餐完成!");
}
private void cookFood() {
try {
System.out.println("我已经开始工作啦 --- 做菜");
Thread.sleep(3000); // 模拟做菜时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("做菜完成!");
}
private void serveFood() {
try {
System.out.println("我已经开始工作啦 --- 上菜");
Thread.sleep(1000); // 模拟上菜时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("上菜完成!");
}
private void billCustomer() {
try {
System.out.println("我已经开始工作啦 --- 结账");
Thread.sleep(500); // 模拟结账时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结账完成!");
}
public static void main(String[] args) {
test t = new test();
Runnable testTask = () -> {
// System.out.println("服务员接受点餐...");
// t.takeOrder();
// System.out.println("服务员传递订单到厨房...");
// t.cookFood();
// System.out.println("服务员上菜...");
// t.serveFood();
// System.out.println("服务员结账...");
// t.billCustomer();
t.serveCustomer();
};
// 测试代码的执行时间,进行10次测试取平均值
PerformanceTester.testPerformance(testTask, 1);
}
}
6 运行示例
6.1 顺序执行
package com.czq.utils.test;
import com.czq.utils.PerformanceTester;
public class test {
public void serveCustomer() {
Thread orderThread = new Thread(this::takeOrder);
Thread cookThread = new Thread(this::cookFood);
Thread serveThread = new Thread(this::serveFood);
Thread billThread = new Thread(this::billCustomer);
orderThread.start(); // 接受点餐
cookThread.start(); // 做菜
serveThread.start(); // 上菜
billThread.start(); // 结账
try {
orderThread.join();
cookThread.join();
serveThread.join();
billThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("所有任务完成!");
}
private void takeOrder() {
try {
System.out.println("我已经开始工作啦 --- 点餐");
Thread.sleep(1000); // 模拟点餐时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("点餐完成!");
}
private void cookFood() {
try {
System.out.println("我已经开始工作啦 --- 做菜");
Thread.sleep(3000); // 模拟做菜时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("做菜完成!");
}
private void serveFood() {
try {
System.out.println("我已经开始工作啦 --- 上菜");
Thread.sleep(1000); // 模拟上菜时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("上菜完成!");
}
private void billCustomer() {
try {
System.out.println("我已经开始工作啦 --- 结账");
Thread.sleep(500); // 模拟结账时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结账完成!");
}
public static void main(String[] args) {
test t = new test();
Runnable testTask = () -> {
System.out.println("服务员接受点餐...");
t.takeOrder();
System.out.println("服务员传递订单到厨房...");
t.cookFood();
System.out.println("服务员上菜...");
t.serveFood();
System.out.println("服务员结账...");
t.billCustomer();
// t.serveCustomer();
};
// 测试代码的执行时间,进行10次测试取平均值
PerformanceTester.testPerformance(testTask, 1);
}
}
输出:
服务员接受点餐...
我已经开始工作啦 --- 点餐
点餐完成!
服务员传递订单到厨房...
我已经开始工作啦 --- 做菜
做菜完成!
服务员上菜...
我已经开始工作啦 --- 上菜
上菜完成!
服务员结账...
我已经开始工作啦 --- 结账
结账完成!
Average operation took 5524 milliseconds.
6.2 多线程
package com.czq.utils.test;
import com.czq.utils.PerformanceTester;
public class test {
public void serveCustomer() {
Thread orderThread = new Thread(this::takeOrder);
Thread cookThread = new Thread(this::cookFood);
Thread serveThread = new Thread(this::serveFood);
Thread billThread = new Thread(this::billCustomer);
orderThread.start(); // 接受点餐
cookThread.start(); // 做菜
serveThread.start(); // 上菜
billThread.start(); // 结账
try {
orderThread.join();
cookThread.join();
serveThread.join();
billThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("所有任务完成!");
}
private void takeOrder() {
try {
System.out.println("我已经开始工作啦 --- 点餐");
Thread.sleep(1000); // 模拟点餐时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("点餐完成!");
}
private void cookFood() {
try {
System.out.println("我已经开始工作啦 --- 做菜");
Thread.sleep(3000); // 模拟做菜时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("做菜完成!");
}
private void serveFood() {
try {
System.out.println("我已经开始工作啦 --- 上菜");
Thread.sleep(1000); // 模拟上菜时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("上菜完成!");
}
private void billCustomer() {
try {
System.out.println("我已经开始工作啦 --- 结账");
Thread.sleep(500); // 模拟结账时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结账完成!");
}
public static void main(String[] args) {
test t = new test();
Runnable testTask = () -> {
// System.out.println("服务员接受点餐...");
// t.takeOrder();
// System.out.println("服务员传递订单到厨房...");
// t.cookFood();
// System.out.println("服务员上菜...");
// t.serveFood();
// System.out.println("服务员结账...");
// t.billCustomer();
t.serveCustomer();
};
// 测试代码的执行时间,进行10次测试取平均值
PerformanceTester.testPerformance(testTask, 1);
}
}
输出:
我已经开始工作啦 --- 点餐
我已经开始工作啦 --- 结账
我已经开始工作啦 --- 上菜
我已经开始工作啦 --- 做菜
结账完成!
上菜完成!
点餐完成!
做菜完成!
所有任务完成!
Average operation took 3012 milliseconds.