并发编程是Java语言的重要特性之一,“如何在Java中实现线程”是学习并发编程的入门知识,也是Java工程师面试必备的基础知识。本文从线程说起,然后用代码说明如何在Java中实现线程。

一、什么是线程?

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,也可以使用多线程对运算密集型任务提速。如果使用得当,线程可以有效地降低程序的开发和运维成本,同时能够提升程序的性能。

二、线程和进程有什么区别?

线程是进程的子集,一个进程可以有很多线程。每个进程都有自己的内存空间,可执行代码和唯一进程标识符(PID)。

每条线程并行执行不同的任务。不同的进程使用不同的内存空间(线程自己的堆栈),而所有的线程共享一片相同的内存空间(进程主内存)。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。

三、如何在Java中实现线程?

“如何在Java中实现线程”是学习并发编程入门的必备知识,对于这个问题也是众说纷纭?打开百度搜索一下,一看便知。在信息爆炸的时代,我认为像孙悟空一样有一双火眼金睛是很必要的,分辨出哪些观点更加准确,才能少走弯路。

那究竟有几种方法可以实现线程?哪一家的言论更权威,被更多的开发者所认同呢?毋庸置疑,当然是官网文档了。文档地址

如图中所示:

There are two ways to create a new thread of execution.

One is to declare a class to be a subclass of Thread. ...

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

现在可以肯定地说,在Java中实现线程有两种方式, 分别是继承 Thread 类和实现 Runnable 接口。下面分别用两种方式实现线程。

  • 方法一:继承Thread类。
public class MyThread extends Thread {

    public static void main(String[] args) {
new MyThread().start();
} @Override
public void run() {
System.out.println("用Thread类实现线程");
}
}
  • 方法二:实现Runnable接口。
public class MyRunnable implements Runnable {

    public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
} @Override
public void run() {
System.out.println("用Runnable接口实现线程");
}
}
  • 深入分析

深入去看Thread类的源码,可以看到Thread类实现了Runnable接口。

并且Thread类重写了run方法, run 方法的代码如下:

看过源码可以发现,其实两种方法实现线程的本质是一样的,都是最终调用了 start()方法来新建线程。这两个方法的最主要区别在于 run()方法的内容来源:

继承Thread类: run()方法整体被重写;

实现Runnable接口:最终调用 target.run()。

四、实现 Runnable 接口和继承 Thread 类哪种方式更好?

Runnable和Thread两者最大的区别是Thread是类而Runnable是接口,至于用类还是用接口,取决于继承上的实际需要。Java类是单继承的,实现多个接口可以实现类似多继承的操作。

使用继承 Thread 的方式的话,那么每次想新建一个任务,只能新建一个独立的线程,而这样做的损耗会比较大。而如果采用实现Runnable接口的话,Runnable就相当于一个作业,而Thread才是真正的处理线程,我们需要的只是定义这个作业,然后将作业交给线程去处理,这样就达到了松耦合,也符合面向对象里面组合的使用。

五、总结

当下次再遇到这样的面试题的时候,可以这样硬刚面试官:

Java官方文档说明有两种方式实现线程:继承Thread和实现Runnable接口。

但是深入源码会发现,其实是一种本质方式,只能通过新建Thread类来创建线程,但是类里面的run方法有两种方式来实现,第一种是重写run方法,第二种实现Runnable接口的run方法,然后再把该runnable实例传给Thread类。

用代码说话:如何在Java中实现线程的更多相关文章

  1. 你如何在 Java 中获取线程堆栈?

    kill -3 [java pid] 不会在当前终端输出,它会输出到代码执行的或指定的地方去.比如,kill -3 tomcat pid, 输出堆栈到 log 目录下. Jstack [java pi ...

  2. java中的线程安全

    在Java中,线程的安全实际上指的是内存的安全,这是由操作系统决定的. 目前主流的操作系统都是多任务的,即多个进程同时运行.为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的.分配给别 ...

  3. 如何在Java中调用Python代码

    有时候,我们会碰到这样的问题:与A同学合作写代码,A同学只会写Python,而不会Java, 而你只会写Java并不擅长Python,并且发现难以用Java来重写对方的代码,这时,就不得不想方设法“调 ...

  4. 如何在 Java 中实现最小生成树算法

    定义 在一幅无向图 \(G=(V,E)\) 中,\((u, v)\) 为连接顶点 \(u\) 和顶点 \(v\) 的边,\(w(u,v)\) 为边的权重,若存在边的子集 \(T\subseteq E\ ...

  5. 如何在 Java 中实现 Dijkstra 最短路算法

    定义 最短路问题的定义为:设 \(G=(V,E)\) 为连通图,图中各边 \((v_i,v_j)\) 有权 \(l_{ij}\) (\(l_{ij}=\infty\) 表示 \(v_i,v_j\) 间 ...

  6. 如何在JAVA中实现一个固定最大size的hashMap

    如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...

  7. 如何在java中使用sikuli进行自动化测试

    很早之前写过一篇介绍sikuli的文章.本文简单介绍如何在java中使用sikuli进自动化测试. 图形脚本语言sikuli sikuli IDE可以完成常见的单击.右击.移动到.拖动等鼠标操作,ja ...

  8. 如何在java中跳出当前多重嵌套循环?有几种方法?

    如何在java中跳出当前多重嵌套循环?有几种方法? - 两种方法   - 1.在外层循环定义标记          ok:          for(int i=0;i<100;i++){    ...

  9. 如何在Java中测试类是否是线程安全的

    通过优锐课的java核心笔记中,我们可以看到关于如何在java中测试类是否线程安全的一些知识点汇总,分享给大家学习参考. 线程安全性测试与典型的单线程测试不同.为了测试一个方法是否是线程安全的,我们需 ...

随机推荐

  1. Sequencial Minimal Optimization-a Fast Alg for Training SVM(译文)

  2. [剑指offer] 54. 字符流中第一个不重复的字符

    题目描述 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字符流中读出 ...

  3. X-Admin&ABP框架开发-消息通知

    业务型网站使用过程中,消息通知是一个不可或缺的功能,采用站内通知.短信通知.邮件通知.微信通知等等各种方式都有,ABP框架对这部分工作已经封装的很好了,站在巨人的肩膀上,一览全貌,带来的就是心情舒畅. ...

  4. IO流4

    IO流的分类 根据处理数据类型的不同分为:字符流和字节流 根据数据流向不同分为:输入流和输出流 字符流和字节流 字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象.本质其实就是基于字 ...

  5. c#异常后重试操作

    private void TryConnect(System.Action action)         {             int retries = 3;             whi ...

  6. Spring Cloud微服务接口这么多怎么调试

    导读 我们知道在微服务架构下,软件系统会被拆分成很多个独立运行的服务,而这些服务间需要交互通信,就需要定义各种各样的服务接口.具体来说,在基于Spring Cloud的微服务模式中,各个微服务会基于S ...

  7. Linux(Ubuntu)安装Swift和Swiftlint

    很多时候iOS开发完毕需要接入CI中,而很多CI是基于Linux的,需要在Linux平台安装Swift和Swiftlint,下面就是针对这两个软件的安装步骤. Swift安装 环境 系统:Ubuntu ...

  8. 还在为垂直居中苦恼?CSS 布局利器 flexbox 轻轻松松帮你搞定

    传统的 CSS 布局方式是基于盒模型(它是根据盒子与父盒子以及兄弟盒子的关系确定大小和位置的算法),实现时依赖于 block, inline, table, position, float 这些属性, ...

  9. Nginx编译安装模块(非重装)

    假如原已经安装好的Nginx,现在需要添加一个未被编译安装的ssl模块,我们该怎么办呢?重装,还是有其他的办法?当然不需要重装的,下面我们看下如何实现的. 1.cd到Nginx解压过后的目录[root ...

  10. [转载]关于ActiveMQ集群

    转载于 http://blog.csdn.net/nimmy/article/details/6247289 近日因工作关系,在研究JMS,使用ActiveMQ作为提供者,考虑到消息的重要,拟采用Ac ...