初识多线程
大学生勇闯多线程
如果将一个应用程序的运行称之为进程
那么多线程就是在进程的基础上更加细粒度的调用(cpu的核心数量)
使用多线程可以:
提高我们系统的响应速度(多线程允许程序同时执行多个任务)
提高资源利用率(减少cpu空闲时间)
多线程的创建方式
extends 继承
public class TestThread1 extends Thread{
@Override
public void run() {
System.out.println("线程名称:"+ Thread.currentThread().getName() +"线程输出");
}
/**
* 线程第一种创建方式 通过extends Thread 类实现
*/
public static void main(String[] args) {
new TestThread1().start();
}
}
implements 接口
public class TestThread2 implements Runnable {
@Override
public void run() {
System.out.println("线程执行体");
}
/**
* 线程的第二种创建方式 但是并不推荐这种显式创建方式 而是通过线程池的方式去创建
*/
public static void main(String[] args) {
new Thread(new TestThread2()).start();
for (int i = 0; i < 10; i++) {
System.out.println("主线程正在执行");
}
}
}
因为这种方式只是实现了Runnable 所以没继承到start方法
在创建线程的时候 需要 new Thread(name).start()
使用executor 线程池
默认线程池的创建方式
// 创建一个固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
自定义线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // 线程池大小
4, // 线程池最大线程数
60, // 线程池空闲时间
TimeUnit.HOURS, // 时间单位
new ArrayBlockingQueue<>(10), // 队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
抢票案例
多线程的运用场景
因为多线程是多个线程并发进行 所以存在数据竞争(如丢失更新、读取到脏数据)
常见的线程安全采用加锁的方式(synchronized关键字、ReentrantLock等)
在这里 我们使用 原子变量 AtomicInteger
/**
* 票的数量
*/
private static final AtomicInteger AVAILABLE_TICKETS = new AtomicInteger(30000);
模拟多用户进行抢票
// 创建一个固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
// 模拟多个用户抢票
for (int i = 1; i <= 30000; i++) {
executor.submit(new TicketBuyer("User " + i));
}
// 关闭线程池,不再接受新的任务,等待所有任务完成
executor.shutdown();
while (!executor.isTerminated()) {
// 等待所有任务完成
}
System.out.println("All threads finished, remaining tickets: " + AVAILABLE_TICKETS.get());
}
线程的购票策略
@Override
public void run() {
// 尝试购买票
if (tryToBuyTicket()) {
System.out.println(name + " bought a ticket."+Thread.currentThread().getName());
} else {
System.out.println(name + " failed to buy a ticket, sold out.");
}
}
因为使用了原子变量 所以不需要加锁
private boolean tryToBuyTicket() {
if (AVAILABLE_TICKETS.get() > 0) {
AVAILABLE_TICKETS.decrementAndGet(); // 减少票数
return true;
}
return false;
}
完整代码如下:
public class TicketBookingExample {
/**
* 票的数量
*/
private static final AtomicInteger AVAILABLE_TICKETS = new AtomicInteger(30000);
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
// 模拟多个用户抢票
for (int i = 1; i <= 30000; i++) {
executor.submit(new TicketBuyer("User " + i));
}
// 关闭线程池,不再接受新的任务,等待所有任务完成
executor.shutdown();
while (!executor.isTerminated()) {
// 等待所有任务完成
}
System.out.println("All threads finished, remaining tickets: " + AVAILABLE_TICKETS.get());
}
static class TicketBuyer implements Runnable {
private final String name;
public TicketBuyer(String name) {
this.name = name;
}
@Override
public void run() {
// 尝试购买票
if (tryToBuyTicket()) {
System.out.println(name + " bought a ticket."+Thread.currentThread().getName());
} else {
System.out.println(name + " failed to buy a ticket, sold out.");
}
}
private boolean tryToBuyTicket() {
if (AVAILABLE_TICKETS.get() > 0) {
AVAILABLE_TICKETS.decrementAndGet(); // 减少票数
return true;
}
return false;
}
}
}
转载自:https://juejin.cn/post/7377694677275623424