Java创建线程的三种方式

Java创建线程的三种方式

一、直接使用Thread创建(继承Thread类)

这种方式通过直接覆盖Thread类中的run方法创建线程

  • 继承Thread类
  1. 首先创建一个类,继承自Thread类
  2. 然后重写Thread的run方法,方法里面写要并发执行的代码
  3. 在main方法里面创建线程,使用start方法开启线程。(注意:一定要使用start而不是run方法开启线程。如果直接调用run()方法,程序将执行完run()方法后才会执行main()方法中后面的代码,这样就是单线程执行而不是多线程并发执行了)
//继承Thread类
class MyThread extends Thread{

  	//重写run方法
    public void run() {
        //t1线程
        System.out.println(Thread.currentThread().getName() + " is running");
    }

}

public class Test1 {

    public static void main(String[] args) {

        Thread t = new MyThread();
        //设置线程名字
        t.setName("t1");
      	//开启线程
        t.start();
        //主线程
        System.out.println(Thread.currentThread().getName() + " is running");

    }

}


​ 打印结果:

​ 可以看到是先执行了main线程里面的 sout语句,然后才执行 t1线程的语句。说明是并发执行的。

image-20210202150127470

  • 直接重写Thread方法

    这种方式与上面创建的方式一样,不过会简洁一点。

        public static void main(String[] args) {
    
            Thread t = new Thread(){
                //重写run方法
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " is running");
                }
            };
    
            t.setName("t1");
            t.start();
    
            System.out.println(Thread.currentThread().getName() + " is running");
    
        }
    
    
二、 使用Runnable配合Thread

优点:

​ 把线程任务(要执行的代码)分开,通过组合而不是继承的方式创建了线程。这让代码更加的灵活,

​ Thread 代表线程

​ Runnable 代表任务

    public static void main(String[] args) {
				//创建一个任务
        Runnable runnable = new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getName() + " is running");
            }
        };
				
        //使用Thread类,将runable作为参数创建线程
        Thread t = new Thread(runnable , "t2");
				//开启线程
        t.start();

        System.out.println(Thread.currentThread().getName() + " is running");

    }

结果:

image-20210202150127470

  • 小结

    • 方法1 是把线程和任务合并在了一起,方法2 是把线程和任务分开了

    • 用 Runnable 更容易与线程池等高级 API 配合

    • 用 Runnable 让任务类脱离了 Thread 继承体系,更灵活。使用了组合的方式创建线程。

三、配合Callable接口和Future创建线程

​ 这种方式可以获得线程的返回值,FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况

​ 在使用这个方式创建线程之前,首先要明白FutureTask的继承关系。可以看到FutureTask实现了RunnableFuture接口。而此接口又继承了Runnable和Future接口。所以FutureTask实际上也是一个Runnable,它除了实现Runnable接口以外,还实现了Future接口。而获得线程的返回值正是通过这个接口进行实现的。

image-20210202153335568

image-20210202153346316

  1. 首先要创建实现了Callable接口的实现类MyCallable,实现call方法。Callable接口是一个泛型接口,其类型就是返回值的类型。实现Callable接口中的call()方法,方法的返回类型与泛型的类型相同。

    class MyCallable implements Callable<Integer>{
    		//重写call 方法
        public Integer call() throws Exception {
            System.out.println(Thread.currentThread().getName() + " is running");
            //睡眠1s
            Thread.sleep(1000);
            //返回100
            return 100;
        }
      
    }
    
  2. Callable不能直接获取返回值,需要用FutureTask在外部封装一下再获取返回值

    在使用task.get() 方法获取返回值时,是阻塞式的等待。上面callable接口在返回值之前睡眠了1s,则这个get方法就会阻塞式的等待1s

     public static void main(String[] args) throws ExecutionException, InterruptedException {
    
       			//创建Callable接口实现类
            Callable callable = new MyCallable();
            //创建FutrueTask类
            FutureTask<Integer> task = new FutureTask<>(callable);
    				//创建线程,task实现了Runnable接口
            Thread t = new Thread(task,"t1");
            t.start();
    				//调用get方法获取返回值
            System.out.println(Thread.currentThread().getName() + " " + task.get());
    
        }
    
  • 结果

    执行完线程t1,然后通过get方法获得了返回值

    image-20210202154236403

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值