并发编程是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. Kafka producer拦截器(interceptor)

    Kafka producer拦截器(interceptor) 拦截器原理 Producer拦截器(interceptor)是在Kafka 0.10版本被引入的,主要用于实现clients端的定制化控制 ...

  2. java和golang通过protobuf协议相互通信

    目录 整体结构说明 protobuf2文件 golang客户端 目录结构 生成pb.go文件 main.go util.go java服务端 目录结构 pom.xml application.yml ...

  3. 蓝牙Beacon广播数据包格式以及解析

    目录 1. 获取原始蓝牙广播包 2. 安装WireShark软件 3. 分析Beacon广播包数据 3.1 第一个数据包格式 3.2 第二个数据包格式 3.3 Android程序开发中的蓝牙广播包 4 ...

  4. ssh,公钥和私钥,远程复制

    ssh,公钥和私钥,远程复制 1.openssh 是一个提供远程访问控制的软件 2.ssh 远程主机用户@远程主机ip地址 ssh root@172.25.254.1 The authenticity ...

  5. ThreadPoolExecutor带来的性能问题

    使用线程池,一般情况下会带来性能提升,并且使用线程池管理线程,减少了每个任务调用的开销,通常可以在执行大量异步任务时提供增强的性能. 但是在高并发的情况下,会因为使用不当导致性能下降,并且下降得比较严 ...

  6. <<Modern CMake>> 翻译 2.2 CMake 编程

    <<Modern CMake>> 翻译 2.2 CMake 编程 流程控制 CMake有一个 if 语句, 经年累月之后,现在它已经相当复杂. 您可以在 if 语句中使用全大写 ...

  7. Mysql Atm取款机系统模拟案例

    #创建ATM数据库 CREATE DATABASE ATM; #创建用户CREATE USER `ATMMaster` IDENTIFIED BY '1234';GRANT ALL ON ATM.* ...

  8. codeforces 355A Vasya and Digital Root

    题意就是找出一个长度为k的整数,使得它的root为d,k的可能取值为1-1000. 第一眼看到这个题,无从下手,想到那么长的数,暴力肯定超时.其实不然,题目要求只要输出任何一个满足条件的即可,因为任何 ...

  9. How to extract WeChat chat messages from a smartphone running Android 7.x or above

    A friend of mine she was frustarted in extracting WeChat chat messages from suspect's smartphone run ...

  10. ASP.NET Core MVC 之局部视图(Partial Views)

    1.什么是局部视图 局部视图是在其他视图中呈现的视图.通过执行局部视图生成的HTML输出呈现在调用视图中.与视图一样,局部视图使用 .cshtml 文件扩展名.当希望在不同视图之间共享网页的可重用部分 ...