多线程基础-创建线程

线程的创建

线程的创建有三种方法

  1. 继承Thread类,并重写run方法
  2. 实现Runable接口,并实现run方法
  3. 实现Callabke接口,并实现call方法(此处不介绍)

案例:模拟文件下载
方法一:

public class ThreadTest1 extends Thread {
    private String fileName;

    // 构造方法,传入文件名
    public ThreadTest1(String fileName) {
        this.fileName = fileName;
    }

    @Override
    public void run() {
        download(fileName);
    }

    // 模拟下载方法
    private void download(String file) {
        System.out.println(Thread.currentThread().getName() + " 开始下载:" + file);
        try {
            // 模拟下载耗时
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName() + " 正在下载 " + file + ",进度:" + (i * 20) + "%");
                Thread.sleep(500); // 模拟下载过程
            }
        } catch (InterruptedException e) {
            System.out.println("用户终止");
        }
        System.out.println(Thread.currentThread().getName() + " 下载完成:" + file);
    }

    // 主函数
    public static void main(String[] args) {
        ThreadTest1 t1 = new ThreadTest1("file1.zip");
        ThreadTest1 t2 = new ThreadTest1("file2.mp4");
        ThreadTest1 t3 = new ThreadTest1("file3.pdf");

        // 启动多个线程
        t1.start();
        t2.start();
        t3.start();
    }
}

方法二:

public class ThreadTest2 implements Runnable {
    private String fileName;

    public ThreadTest2(String fileName) {
        this.fileName = fileName;
    }

    @Override
    public void run() {
        download(fileName);
    }

    private void download(String file) {
        System.out.println(Thread.currentThread().getName() + " 开始下载:" + file);
        try {
            for (int i = 1; i <= 5; i++) {
                System.out.println(Thread.currentThread().getName() + " 正在下载 " + file + ",进度:" + (i * 20) + "%");
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " 下载完成:" + file);
    }

    public static void main(String[] args) {
        // 创建 Runnable 实例
        ThreadTest2 task1 = new ThreadTest2("movie.mp4");
        ThreadTest2 task2 = new ThreadTest2("document.pdf");
        ThreadTest2 task3 = new ThreadTest2("game.zip");

        // 将任务交给 Thread 执行
        Thread t1 = new Thread(task1, "下载线程-1");
        Thread t2 = new Thread(task2, "下载线程-2");
        Thread t3 = new Thread(task3, "下载线程-3");

        // 启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

为什么推荐实现 Runnable 接口而不是继承 Thread?

两种方式的本质区别

方式 1:继承 Thread

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程运行中...");
    }
}
new MyThread().start();

Thread 是一个 类,它本身实现了 Runnable 接口;
当你继承它时,你其实是在继承整个线程类的实现;
这样做导致你的类已经“是一个线程对象”。

方式 2:实现 Runnable

class MyTask implements Runnable {
    @Override
    public void run() {
        System.out.println("线程运行中...");
    }
}
new Thread(new MyTask()).start();

这里只定义了要执行的任务逻辑;
线程的启动、管理由 Thread 对象负责;
更加灵活、解耦。

总结: 我们希望各个模块、类的职能更清晰,实现功能的类只关注功能实现,而不必关心线程创建终止的逻辑

posted @ 2025-10-28 16:14  Huaixuxm  阅读(3)  评论(0)    收藏  举报