详解多线程启动涉及的知识点

简介: 详解多线程启动涉及的知识点

Thread类

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易实现资源共享。实现Runnable接口比继承Thread类所具有的优势:

  • 适合多个相同的程序代码的线程去处理同一个资源
  • 可以避免java中的单继承的限制
  • 增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
//继承 Thread
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start();

Runnable接口

// 先看一下java.lang.Runnable,它是一个接口,在它里面只声明了一个run()方法:
// 由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。
public interface Runnable {
    public abstract void run();
}
//实现Runnable接口
Thread2 mTh = new Thread2();
new Thread(mTh, "C").start();//同一个mTh,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常   
new Thread(mTh, "D").start();
new Thread(mTh, "E").start();

这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。

而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。

Callable接口

Callable接口位于java.util.concurrent包下,在它里面也只声明了一个方法,只不过这个方法叫做call()

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

可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。Callable接口可以看作是Runnable接口的补充,call方法带有返回值,并且可以抛出异常。

FutureTask类

如何获取Callable的返回结果呢?一般是通过FutureTask这个中间媒介来实现的。整体的流程是这样的:

  • 把Callable实例当作参数,生成一个FutureTask的对象
  • 然后把这个对象当作一个Runnable,作为参数另起线程。

由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。下面以Thread包装线程方式启动来说明一下。

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class Demo {
    public static void main(String[] args) throws Exception {
        Callable<Integer> call = new Callable<Integer>() {
            public Integer call() throws Exception {
                System.out.println("计算线程正在计算结果...");
                Thread.sleep(3000);
                return 1;
            }
        };
        FutureTask<Integer> task = new FutureTask<>(call);
        Thread thread = new Thread(task);
        thread.start();
        System.out.println("main线程干点别的...");
        Integer result = task.get();
        System.out.println("从计算线程拿到的结果为:" + result);
    }
}

Future接口

FutureTask继承体系中的核心接口是Future。

Future的核心思想是:一个方法,计算过程可能非常耗时,等待方法返回,显然不明智。可以在调用方法的时候,立马返回一个Future,可以通过Future这个数据结构去控制方法f的计算过程。这里的控制包括:

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);//还没计算完,可以取消计算过程
    boolean isCancelled();///判断计算是否被取消
    boolean isDone();//判断是否计算完
    V get() throws InterruptedException, ExecutionException;
    //获取计算结果(如果还没计算完,也是必须等待的)
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

也就是说Future提供了三种功能:

  • 判断任务是否完成;
  • 能够中断任务;
  • 能够获取任务执行结果。

实现Runnable接口和Callable接口的区别

如果想让线程池执行任务的话需要实现的Runnable接口或Callable接口。

Runnable接口或Callable接口实现类都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行。两者的区别在于 Runnable 接口不会返回结果但是 Callable 接口可以返回结果。

备注:工具类 Executors 可以实现 Runnable 对象和 Callable 对象之间的相互转换。
Executors.callable(Runnable task)也就是说Future提供了三种功能:

  • 判断任务是否完成;
  • 能够中断任务;
  • 能够获取任务执行结果。Executors.callable(Runnable task,Object resule )。
相关文章
|
Java
Java线程知识点总结
Java线程知识点总结
59 0
|
6月前
|
安全 Java
Java多线程(全知识点)(下)
Java多线程(全知识点)(下)
64 0
|
15天前
|
Java Python
python知识点100篇系列(16)-python中如何获取线程的返回值
【10月更文挑战第3天】本文介绍了两种在Python中实现多线程并获取返回值的方法。第一种是通过自定义线程类继承`Thread`类,重写`run`和`join`方法来实现;第二种则是利用`concurrent.futures`库,通过`ThreadPoolExecutor`管理线程池,简化了线程管理和结果获取的过程,推荐使用。示例代码展示了这两种方法的具体实现方式。
python知识点100篇系列(16)-python中如何获取线程的返回值
|
2月前
|
存储 消息中间件 资源调度
「offer来了」进程线程有啥关系?10个知识点带你巩固操作系统基础知识
该文章总结了操作系统基础知识中的十个关键知识点,涵盖了进程与线程的概念及区别、进程间通信方式、线程同步机制、死锁现象及其预防方法、进程状态等内容,并通过具体实例帮助理解这些概念。
「offer来了」进程线程有啥关系?10个知识点带你巩固操作系统基础知识
|
5月前
|
安全 Java 编译器
JAVA-多线程知识点总结(二)
JAVA-多线程知识点总结(二)
|
6月前
|
Java 调度
Java多线程(全知识点)(上)
Java多线程(全知识点)
80 0
|
6月前
|
存储 安全 Java
并发编程知识点(volatile、JMM、锁、CAS、阻塞队列、线程池、死锁)
并发编程知识点(volatile、JMM、锁、CAS、阻塞队列、线程池、死锁)
101 3
|
4月前
|
存储 并行计算 安全
Java面试题:Java内存管理、多线程与并发框架的面试题解析与知识点梳理,深入Java内存模型与垃圾回收机制,Java多线程机制与线程安全,Java并发工具包与框架的应用
Java面试题:Java内存管理、多线程与并发框架的面试题解析与知识点梳理,深入Java内存模型与垃圾回收机制,Java多线程机制与线程安全,Java并发工具包与框架的应用
73 0
|
5月前
|
Oracle Java 关系型数据库
面试知识点:notify是随机唤醒线程吗(唤醒线程顺序)?
面试知识点:notify是随机唤醒线程吗(唤醒线程顺序)?
113 0
|
5月前
|
设计模式 安全 Java
JAVA-多线程知识点总结(三)
JAVA-多线程知识点总结(三)