线程的创建方式

线程的创建方式

1、继承Thread类实现

如何实现?

  1. 继承Thread类
  2. 重写run方法
  3. 创建线程对象
  4. 调用start()方法
/**
 * @author Leah
 * @Description:多线程创建方式一:继承Thread类实现
 * @Title: ThreadDemo1
 * @Package com.threadPool.Thread
 * @date 2022-05-12 14:55
 */
public class ThreadDemo1 {
    public static void main(String[] args) {
        //3、new一个新线程对象
        Thread t=new MyThread();
        //4、调用start方法启动线程(执行的是run方法)
        t.start();

        for (int i=0;i<5;i++){
            System.out.println("主线程执行输出"+i);
        }
    }
}

/**
 * 1、定义一个线程类继承Thread
 */
class MyThread extends Thread{
    /**
     * 2、重写run方法,里面是定义线程以后要干啥
     */
    @Override
    public void run(){
        for (int i=0;i<5;i++){
            System.out.println("子线程执行输出"+i);
        }
    }
}

输出结果,主线程和子线程同时执行
优缺点:

  • 优点 :代码简单
  • 缺点 :
    ①继承 thread类,导致不能继承其他类,不便于拓展
    ②如果线程有执行结果是不可以直接返回的,run方法返回类型是void,

思考
为啥不直接调用run方法,而是调用start启动线程

  • 直接调用run方法会当成普通方法执行,那就不会创建新的线程,还是当线程执行,只有一个main方法的线程
  • 只有调用start方法才会启动一个新的线程执行

注意
如果主线程任务放在子线程之前了,那么也就相当于当线程的效果了

2、实现Runnable接口

步骤:

  • 定义一个线程任务类实现Runnable 接口,实现run方法

The other way to create a thread is to declare a class that implements the Runnable interface.That class then implements the run method.

  • 创建线程任务类,并交给thread 处理,调用线程对象的start()方法启动线程

An instance of the class can be allocated, passed as an argument when creating Thread, and started.

/**
 * @author Leah
 * @Description:多线程创建方式二:继承Thread类实现
 * @Title: ThreadDemo1
 * @Package com.threadPool.Thread
 * @date 2022-05-12 14:55
 */
public class ThreadDemo2 {
    public static void main(String[] args) {
        //3、new一个任务对象
        Runnable target=new MyRunnable();
        //把任务对象交给Thread处理
        Thread t=new Thread(target);
        //4、调用start方法启动线程
        t.start();
        for (int i=0;i<5;i++){
            System.out.println("主线程执行输出"+i);
        }
    }
}

/**
 * 1、定义一个线程任务类,实现Runnable接口
 */
class MyRunnable implements Runnable{
    /**
     * 2、实现run方法,里面是定义线程以后要干啥(执行任务)
     */
    @Override
    public void run(){
        for (int i=0;i<5;i++){
            System.out.println("子线程执行输出"+i);
        }
    }
}

匿名内部类写法

public class ThreadDemo2Other {
    public static void main(String[] args) {
        //匿名内部类方式
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<5;i++){
                    System.out.println("子线程1执行输出"+i);
                }
            }
        }).start();
        //lambda方式简化后
        new Thread(()-> {
            for (int i=0;i<5;i++){
                System.out.println("子线程2执行输出"+i);
            }
        }).start();
        //4、调用start方法启动线程
        for (int i=0;i<5;i++){
            System.out.println("主线程执行输出"+i);
        }
    }

输出结果,主线程和子线程同时执行
优缺点:

  • 优点 :线程任务类只是实现接口,拓展性强
  • 缺点 :
    ①编程多一层对象包装
    ②如果线程有执行结果是不可以直接返回的,run方法返回类型是void,不适合需要返回线程执行结果的业务场景

那么如何解决上面两种方式无返回值的问题呢?
那就用到第三种方式

3、利用Callable、FutureTask接口实现

步骤:
1、得到任务对象
①定义一个任务类,实现Callable接口,重写call方法(任务方法),封装要做的事
②用FutureTask把Callable对象封装成线程任务对象
2、把线程任务对象交给线程对象处理,并启动线程
3、执行完毕后,通过FutureTask的get方法获取执行返回结果


import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * @author Leah
 * @Description: 实现Callable接口,结合FutureTask完成
 * @Title: ThreadDemon3
 * @Package com.threadPool.Thread
 * @date 2022-05-12 16:57
 */
public class ThreadDemon3 {
    public static void main(String[] args) {
        //创建Callable任务对象,并把Callable任务对象交给FutureTask对象
        //FutureTask对象的作用1:是Runnable的对象(实现了Runnable接口),可以交给Thread
        //FutureTask对象的作用2:可以在线程执行完毕时调用其get方法得多线程执行完的结果
        FutureTask<String> futureTask1 = new FutureTask<>(new MyCallable("1"));
        //交给线程处理,并启动线程
        new Thread(futureTask1).start();
        FutureTask<String> futureTask2 = new FutureTask<>(new MyCallable("2"));
        new Thread(futureTask2).start();
        try {
            //如果futureTask1任务没有执行完毕,这里的代码会等待,知道线程跑完才提取结果
            String s1 = futureTask1.get();
            System.out.println(s1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            String s1 = futureTask2.get();
            System.out.println(s1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
/**
 * 1、定义一个任务类,实现Callable接口 应该申明线程任务执行完毕后的返回结果的数据类型
 */
class MyCallable implements Callable<String>{
    private String value;
    public MyCallable(String value) {
        this.value = value;
    }

    /*
     *重写call方法(任务方法),封装要做的事
     * @throws Exception
     */
    @Override
    public String call() throws Exception {
        for (int i=0;i<5;i++){
            System.out.println("子线程"+value+"执行输出"+i);
        }
        return "子线程返回值"+value;
    }
}

结果:
子线程1执行输出0
子线程1执行输出1
子线程1执行输出2
子线程1执行输出3
子线程2执行输出0
子线程1执行输出4
子线程2执行输出1
子线程2执行输出2
子线程2执行输出3
子线程返回值1
子线程2执行输出4
子线程返回值2

优缺点:

  • 优点 :可拓展,可得到执行结果返回值
  • 缺点 :代码复杂了点
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值