start()和run()的区别
package com.process;
class MyThread extends Thread {
    @Override
    public void run() {
        for(int i=0;i<1000;i++) {
            // 模拟线程执行的任务
            System.out.println("Son thread is running: " + i);
        }
    }
}
public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start(); // 启动线程
        for(int i=0;i<1000;i++) {
        // 模拟主线程执行的任务
            System.out.println("Main thread is running: " + i);
        }
    }
}
会发现主线程和子线程的代码交替执行
  
  
  需要说明把 thread.start()换成thread.run()并不会创建一个线程,run()只是进行方法的调用!
另一个例子
继承Thread类、实现Runnable接口、实现Callable接口分别来创建线程
其中Java是单继承,如果继承了Thread,就不能继承其他类,扩展性差,所以实际开发中一般不使用继承Thread类的方法!
package com.process;
import  java.io.File;
import  java.io.IOException;
import java.net.URL;
import org.apache.commons.io.FileUtils;
class MyThread extends Thread {
    final private String url;
    final private String name;
    public MyThread(String url, String name) {
        this.url = url;
        this.name = name;
    }
    @Override
    public void run() {
        webDownloader wd = new webDownloader();
        wd.downloader(url, name);
        System.out.println("下载了文件名为:" + name);
    }
}
class MyRunneable implements Runnable{
    final private String url;
    final private String name;
    public MyRunneable(String url, String name) {
        this.url = url;
        this.name = name;
    }
    @Override
    public void run()
    {
        webDownloader wd = new webDownloader();
        wd.downloader(url, name);
        System.out.println("下载了文件名为: "+ name);
    }
}
class webDownloader {
    public void downloader(String url, String name) {
        try {
            FileUtils.copyURLToFile(
                new URL(url),
                new File(name)
            );
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}
public class Main {
    public static void main(String[] args) {
        //1.用Thread类的子类来实现多线程
        MyThread t1 = new MyThread("https://img-s.msn.cn/tenant/amp/entityid/AA1Hk338.img?w=768&h=482&m=6", "1.jpg");
        MyThread t2 = new MyThread("https://img-s.msn.cn/tenant/amp/entityid/AA1HhWxW.img?w=584&h=328&m=6", "2.jpg");
        MyThread t3 = new MyThread("https://img-s.msn.cn/tenant/amp/entityid/AA1HhUci.img?w=584&h=328&m=6", "3.jpg");
        t1.start();
        t2.start();
        t3.start();
        //2.用Runnable接口来实现多线程
        Thread t4=new Thread(new MyRunneable("https://img-s.msn.cn/tenant/amp/entityid/AA1HhUci.img?w=584&h=328&m=6", "4.jpg"));
        Thread t5=new Thread(new MyRunneable("https://img-s.msn.cn/tenant/amp/entityid/AA1HhWxW.img?w=584&h=328&m=6", "5.jpg"));
        Thread t6=new Thread(new MyRunneable("https://img-s.msn.cn/tenant/amp/entityid/AA1Hk338.img?w=768&h=482&m=6", "6.jpg"));
        t4.start();
        t5.start();
        t6.start();
    }
}
输出为
下载了文件名为:2.jpg
下载了文件名为:3.jpg
下载了文件名为:5.jpg
下载了文件名为:4.jpg
下载了文件名为:6.jpg
下载了文件名为:1.jpg
Runnable和Callable区别
// Runnable
public interface Runnable {
    void run();
}
// Callable
public interface Callable<V> {
    V call() throws Exception;
}
java线程的本质
这里梳理一下
1. 线程的本质创建方式
无论你是继承Thread类、实现Runnable接口、实现Callable接口、还是用线程池,
最终真正创建线程的,都是new Thread().start()。
- 继承Thread类:你写的其实是线程要执行的“任务体”,本质还是Thread对象在调度。
- 实现Runnable/Callable接口:你只是把任务封装成对象,最后还是交给Thread来启动。
- 线程池/CompletableFuture:底层也是维护了一组Thread对象,帮你统一管理和复用。
所以,Java真正意义上的线程创建,只有new Thread().start()这一种。其他方式只是任务的封装和管理方式。
2. 线程体和线程的区别
- 
线程(Thread):是操作系统调度的最小执行单元,Java里表现为Thread对象。
- 
线程体:是线程要执行的具体代码,也就是你写在run()方法里的内容(任务体)。
举例:
class MyRunnable implements Runnable {
    public void run() {
        // 这里就是线程体
        System.out.println("任务执行");
    }
}
Thread t = new Thread(new MyRunnable()); // 这里创建了线程对象
t.start(); // 启动线程,线程体开始执行
3. 总结
- 所有多线程写法,最终都要依赖Thread对象的start()方法来真正创建和启动线程。
- 你写的run()方法、Runnable、Callable等只是“线程体”,是线程要执行的任务内容。
- “线程体”是任务,“线程”是执行任务的实体。
面试答法:
Java真正创建线程的方式只有
new Thread().start(),其他方式只是任务的封装和管理。线程体是线程要执行的代码,线程是调度和运行这些代码的实体。
 

 
    
Top comments (0)