每日智识
柔彩主题三 · 更轻盈的阅读体验

Java多线程:让程序同时做几件事

发布时间:2025-12-24 18:20:31 阅读:463 次

你有没有试过一边煮咖啡,一边煎鸡蛋?在厨房里,这两件事可以同时进行,互不耽误。计算机世界里也有类似的操作方式——Java线程就是让一个程序同时干好几件事的技术。

什么是线程?

每个Java程序启动时,默认会开启一个主线程。你可以把它想象成一个工人,按顺序执行任务。但如果任务多了,一个工人忙不过来,就得请更多人一起上。这些“工人”就是线程。

比如你在写一个文件上传功能,主线程负责界面响应,另一个线程在后台上传文件。这样即使上传卡住,界面也不会冻结。

创建线程的两种常用方式

第一种是继承 Thread 类,重写 run() 方法:

class MyThread extends Thread {
    public void run() {
        System.out.println("我在子线程工作");
    }
}

// 启动线程
MyThread t = new MyThread();
t.start(); // 注意:不能直接调用 run()

第二种是实现 Runnable 接口,更推荐这种方式,因为Java不支持多继承:

class Task implements Runnable {
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            try {
                Thread.sleep(1000); // 暂停1秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

// 使用
Thread t = new Thread(new Task());
t.start();

线程安全问题:别让数据乱了套

多个线程同时修改同一个变量时,容易出问题。比如银行账户余额,两个线程同时取钱,可能都读到相同的余额,导致超支。

这时候需要用 synchronized 关键字来加锁:

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

加上 synchronized 后,同一时间只有一个线程能进入方法,数据就不会冲突。

用线程池管理线程

频繁创建和销毁线程很耗资源。就像每次做饭都招新厨师,成本太高。更好的做法是建个“厨师团队”,重复使用。

Java 提供了 ExecutorService 来管理线程池:

ExecutorService pool = Executors.newFixedThreadPool(3);

for (int i = 0; i < 5; i++) {
    pool.execute(new Task());
}

// 用完记得关闭
pool.shutdown();

这样最多同时运行3个线程,其余任务排队等待,系统更稳定。

实际场景:抢票系统模拟

春运抢票时,成千上万人同时点击。我们可以用多线程模拟这个场景:

public class TicketSeller {
    private static int tickets = 10;

    public static synchronized void sell() {
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + " 卖出第 " + tickets-- + " 张票");
        }
    }

    public static void main(String[] args) {
        ExecutorService pool = Executors.newCachedThreadPool();
        for (int i = 0; i < 20; i++) {
            pool.execute(TicketSeller::sell);
        }
        pool.shutdown();
    }
}

虽然有20个“用户”抢票,但只有10张票会被成功卖出,后面的会发现没票了。同步方法保证了不会出现负数票或重复卖票。

多线程不是万能药,用不好反而会让程序更难调试。关键是理解什么时候需要并发,什么时候该加锁,以及如何合理分配资源。