第一种方式 继承Thread类

//1)继承Thread
public class ThreadDemo extends Thread {
//2)重写run方法
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println("ThreadDemo"+i);
        }
    }
}
class Test04{
    public static void main(String[] args) {
//3)创建线程对象
        ThreadDemo t1 = new ThreadDemo();
// 4)启动新的线程 自动执行run()方法
        t1.start();   
        for(int i=1;i<10;i++){
            System.out.println("main"+i);
        }
    }
    /*
    *在当前程序main 和 t1线程在同时执行,每次运行的结果可能不一样
    * 多线程程序中的多个线程 谁抢到cpu谁执行
    * */

}

第二种方式:实现Runnable接口

1、使用 定义实现类方式实现Runnable接口

//1)继承Runnable接口
public class RunnableDemo implements Runnable {
    //2)重写Runnable接口中的run方法
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println("RunnableDemo"+i);
        }
    }
}
class test05{
    public static void main(String[] args) {
        //3)创建线程对象
        RunnableDemo p = new RunnableDemo(); //Runnable接口实现类对象
        //4)Thread(Runnable)构造方法的形参是接口,在调用方法时传递接口的实现类对象
        Thread t2 = new Thread(p);
        //5)开启线程
        t2.start();
        Thread t3 = new Thread(p);
        t3.start();

        //main线程
        for(int i =1;i<90;i++){
            System.out.println("main-----"+i);
        }
    }
}

2、使用 匿名的内部类实现Runnable接口

当接口的实现类只使用一次,或抽象类的子类只使用一次时,就不需要在定义一个类,可以直接使用匿名的内部类

//1)继承Runnable接口
public class RunnableDemo implements Runnable {
    //2)重写Runnable接口中的run方法
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println("RunnableDemo"+i);
        }
    }
}
class test06{
    public static void main(String[] args) {
        //在调用方法时,实参是接口匿名内部类对象
        Thread t22 = new Thread(new Runnable() {
            //在匿名内部类中重写抽象方法
            @Override
            public void run() {
                //指定子线程要打印的代码
                for(int i =1;i<90;i++){
                    System.out.println("t22-----"+i);
                }
            }
        });
        t22.start();
        //main线程
        for(int i =1;i<90;i++) {
            System.out.println("main-----" + i);
        }
    }
}

第三种方式:实现 Callable接口(Callable接口有返回值 Runnable接口无返回值)

public class CallableDemo implements Callable {
    //1)重写抽象方法call方法
    @Override
    public Integer call() throws Exception {
        int result = new Random().nextInt(100);
        System.out.println("执行子线程完成某次计算,结果为"+result);
        return result;
    }
}
class test07{
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //2)创建Callable接口实现类对象
        CallableDemo callableDemo = new CallableDemo();
        //FutureTask实现了RunnableFuture接口,RunnableFuture继承了Runnable接口,FutureTask接口就是Runnable接口的实现类
        FutureTask<Integer> task = new FutureTask<>(callableDemo);
        Thread t3 = new Thread(task); //线程池:省去了创建线程、释放线程的时间
        //3)开启新的线程
        t3.start();
//        System.out.println("当前线程是main线程,可以获得子线程的执行结果:");
//        System.out.println("result="+task.get());
    }
}