线程的创建方式

[Q&A] 线程的创建方式?

Java创建多线程只有一种方式: Thread! 有且仅有 Thread 类能通过 start0() 方法 向操作系统申请线程资源

在很多软文以及一些书籍中,经常会提到,创建线程有两种方式,第一种是构造一个Thread,第二种是实现Runnable接口,这种说法是错误的,最起码是不严谨的,在JDK中代表线程的就只有Thread这个类,线程的执行单元就是run方法,你可以通过继承Thread然后重写run方法实现自己的业务逻辑,也可以实现Runnable接口实现自己的业务逻辑。
-----------------------------------------------------------------------------读书笔记摘自书名:Java高并发编程详解:多线程与架构设计 作者:汪文君

在这里插入图片描述

通俗所说的线程创建方式

1. 继承Thread类

public class ExtendsRunningMan extends Thread {
    private String threadTaskName;

    public ExtendsRunningMan(String name) {
        this.threadTaskName = name;
    }

    @Override
    public void run() {
        for (int i = 0; i <= 10; i++) {
            System.out.println(Thread.currentThread().getId() + " " + Thread.currentThread().getName() + threadTaskName + i);
        }
    }
}

ExtendsRunningMan r1 = new ExtendsRunningMan("小明");
r3.start();
# 优点
符合大家的编程习惯	

# 缺点
因为java类的单继承。如果当前类继承 Thread 类之后就不可以继承其他类。如果我们的类已经继承了一个类,则无法再继承 Thread 类。

应该怎么办呢?→ 引出第二种方式


2. 实现Runnable接口

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

public class RunnableRunningMan implements Runnable {
    private String name;

    public RunnableRunningMan(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getId() + " " + Thread.currentThread().getName() + " " + name + " " + i);
        }
    }
}


# 场景1:3个 Thread共享这个Runnable对象中的代码
RunnableRunningMan r1 = new RunnableRunningMan("小明");

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
Thread t3 = new Thread(r1);

t1.start();
t2.start();
t3.start();


# 场景2:3个Thread独立执行各自Runnable对象中的代码
RunnableRunningMan r1 = new RunnableRunningMan("小明");
RunnableRunningMan r2 = new RunnableRunningMan("小张");
RunnableRunningMan r3 = new RunnableRunningMan("小李");

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);

t1.start();
t2.start();
t3.start();
# 优点
1、可以避免由于Java的 单继承 特性而带来的局限	
2、Runnable是可以 共享数据 的,适合多个线程处理同一资源的情况
# 个人理解是 :多线程的是避免浪费。多个Thread可以同时加载一个Runnable实例,是为了这个分的时间片的概率高,执行的更快点。

# 缺点
1、Runnable是可以共享数据的,可能会造成线程的不安全 (Runnable 造成线程的不安全)
2、Runnable是执行工作的独立任务,但是它不返回任何值

Runnable 造成线程的不安全

如果你希望任务在完成后能返回一个值,应该怎么办呢? → 引出第三种方式


3. 实现Callable接口

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

public class CallableRunningMan implements Callable<Integer> {
    private String name;

    public CallableRunningMan(String name) {
        this.name = name;
    }

    @Override
    public Integer call() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName() + " " + name + " " + i);
        }
        return 100;
    }
}


CallableRunningMan myThread1 = new CallableRunningMan("小明");
FutureTask<Integer> futureTask1 = new FutureTask<>(myThread1);

CallableRunningMan myThread2 = new CallableRunningMan("小明");
FutureTask<Integer> futureTask2 = new FutureTask<>(myThread2);

new Thread(futureTask1).start();
new Thread(futureTask2).start();

try {
    System.out.println(Thread.currentThread().getName() + "返回值" + futureTask1.get());
    System.out.println(Thread.currentThread().getName() + "返回值" + futureTask2.get());
} catch (InterruptedException e) {
    throw new RuntimeException(e);
} catch (ExecutionException e) {
    throw new RuntimeException(e);
}

Runnable接口 和 Callable接口的区别

Runnable	                 Callable
Since java1.1	             Since java1.5
run()	                     call()
无返回值	                     有返回值,FutureTask对象
不可抛异常	                 可以抛异常
加入线程池使用execute方法	     加入线程池使用submit方法                

参考

创建线程到底有多少种方式?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值