Java线程介绍

通常情况下,在一个服务器上面运行的程序是很多的,可能同一时间会有多个客户
端的程序访问服务器,服务器都要对这些客户端做出响应。如果我们处理器有限,
只有一个处理器的时候,如何能够让这些任务看起来是并行的同时执行呢?这里就需要用到线程的知识。

当有超过一个以上执行空间时,看起来会像是有好几件事同时发生。但实际上,只有真正的多处理器系统才可以同时执行好几件事。使用java多线程可以让它看起来好像同时都在执行,也就是说,执行的动作可以在执行空间中快速切换,因此感觉上好像是每一个任务都在同时执行。在Java中,我们用Thread这个类来实现这一点。

下面我们通过代码一起来看一下如何新建一个线程(ThreadTest)。首先,我们需要新建一个Runnable对象。稍后我们会再定义Runnable类。而这个类会定义线程会执行什么样的任务。之后,我们会定义Thread对象,用它来去执行Runnable定义好的任务。然后,启动Thread,将Runnable对象的方法摆到新的执行空间中。

package web_server;public class ThreadTest {public static void main(String[] args) {// 新建Runnable对象Runnable threadJob = new MyRunnable();// 将Runnable的实例传给Thread的构造函数Thread myThread = new Thread(threadJob);// 调用start()才会让线程开始执行,在此之前// 它只是Thread一个实例,并不是真的线程myThread.start();System.out.println("back in main");}}

接下来我们再看如何实现Runnable。Runnable是一个接口,该接口只有一个方法,就是public void run()。在run中定义要执行的方法。因为Runnable是一个接口,线程的任务是可以被定义在任何实现Runnable的类上。线程只在乎传入给Thread的构造函数的参数是否为实现Runnable的类。当你把Runnable传给Thread的构造函数时,实际上就是在给Thread取得run的办法,这就等于你给Thread一项任务。

package web_server;public class MyRunnable implements Runnable{// Runnable接口只有一个方法,就是public void run()public void run() {go();}public void go() {doMore();}public void doMore() {System.out.println("top o' the stack");}
}

线程的原子性

每一个线程变成可执行状态之后,它就会在可执行和不可执行两种状态中来来回回的切换,有的时候也会出现第三种状态,就是暂时不可执行状态。现在假设你有多个线程在排队等待执行,这时候哪个线程先执行,具体执行多长时间呢?这些工作都由调度器来实现。线程调度器会去决定哪个线程跑起来,而哪个线程会暂时不去执行。

但是这样又会有一个大问题,特别是对于多线程而言,可能会发生a线程执行一段时间,然后b线程再执行一段时间。如果a线程和b线程的程序方法互不影响还好,如果a线程和b线程使用的是同样的程序方法,可能会发生结果互相影响的问题。对于这样的问题,我们可以通过Synchronized来解决。Synchronized关键字代表线程需要一把钥匙来存取被同步化过程的线程。也就是说,通过synchronized同步化修饰过后的方法,会将方法中的内容执行完之后,再交给别的线程去执行。如果想要保护重要的数据,就把作用在数据上的方法给同步化。这部分程序,不可分割,应该被连续的执行。在古典物理学中,我们认为原子是不可分割的最小物理单元。因此我们说synchronized修饰过的方法具有原子性。我们下面通过一个例子一起来看一下。

package web_server;public class TestSync implements Runnable{private int balance = 0;public void run() {for(int i = 0; i < 50; i++) {increment();System.out.println("balance is " + balance);}}public void increment() {//  public synchronized void increment() {int i = balance;balance = i + 1;}}
package web_server;public class TestSyncTest {public static void main(String[] args) {// TODO Auto-generated method stubTestSync job = new TestSync();Thread a = new Thread(job);Thread b = new Thread(job);a.start();b.start();}}

可以看到,使用synchronized之后执行的效果看起来很正常,而不加之后有一些怪异的值。我们这里新建了两个线程,这两个线程执行的都是同样的方法。之所以不适用synchronized会出现数字乱的问题在于,比如说执行了i=balance之后,a线程就切换成b线程去执行了。还没有来得及累加。B线程执行一段时间之后再切换成a线程,然后a线程再继续累加,就会出现数字错乱的问题。而使用synchronized会让其强制执行完累加之后再去切换线程,所以不会出现错乱。

最后附上 本文内容对应的视频讲解

参考资料

《Head First Java》

Java线程通俗讲解相关推荐

  1. Java多数据源最通俗讲解

    Java多数据源最通俗讲解 before after 理论 实操 编码 小总结 before 项目中可能会用到很多的数据源,例如目前这个项目中用到了五个数据源,那么数据源的 配置和数据源的切换就成为了 ...

  2. Java线程同步学习,线程不安全案例讲解,同步方法和同步块 synchronized

    本文主要是自己学习多线程时,所做的笔记,参考的是b站狂神说Java多线程视频讲解. 目录如下: 文章目录 线程同步 一.三大线程不安全案例 1.买票案例 2.不安全取钱 3.线程不安全 二.同步方法及 ...

  3. Java线程的6种状态及切换(透彻讲解)

    Java中线程的状态分为6种. 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法. 2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running ...

  4. 网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

    1.前言 标题虽然是为了解释有了 IP 地址,为什么还要用 MAC 地址,但是本文的重点在于理解为什么要有 IP 这样的东西.本文对读者的定位是知道 MAC 地址是什么,IP 地址是什么. (本文同步 ...

  5. 蓝牙聊天App设计3:Android Studio制作蓝牙聊天通讯软件(完结,蓝牙连接聊天,结合生活情景进行蓝牙通信的通俗讲解,以及代码功能实现,内容详细,讲解通俗易懂)

    前言:蓝牙聊天App设计全部有三篇文章(一.UI界面设计,二.蓝牙搜索配对连接实现,三.蓝牙连接聊天),这篇文章是:三.蓝牙连接聊天. 课程1:Android Studio小白安装教程,以及第一个An ...

  6. 第二十三章 Java线程与操作系统关系

    Java线程与操作系统关系 Java线程的实现方式 线程的实现 内核线程实现 用户线程实现 用户线程加轻量级进程混合实现 Java线程的实现 Java线程调度 线程状态转换 线程安全 线程安全分类 线 ...

  7. Java线程状态完全解析教程

    简介 Java线程有6种状态,分别是NEW.RUNNABLE.BLOCKED.WAITING.TIMED_WAITING.TERMINATED.本文讲解线程状态变化的流程以及用代码演示通过调用哪些方法 ...

  8. Java线程池面试必备:核心参数、工作流、监控、调优手段

    欢迎关注方志朋的博客,回复"666"获面试宝典 1. Java的线程池 ① 合理使用线程池的好处 Java的线程池是运用场景最多的并发框架,几乎所有需要异步或者并发执行任务的程序都 ...

  9. Java线程池实现原理及其在美团业务中的实践

    来自:美团技术团队 随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流.使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器.J.U.C提供的线程池ThreadPoolExecuto ...

最新文章

  1. 如何使用Next.js创建动态的Rick and Morty Wiki Web App
  2. SpringBoot整合Swagger测试api构建
  3. PageRequestManagerServerError
  4. PHP开发绝对不能违背的安全铁则!
  5. GitLab CI/CD
  6. android日常开发60条经验
  7. 前后端开发的心得体会_社招后端三面总结以及学习经验感言(操详细)
  8. Node连接MySQL数据库进行基本的增删改查操作(一看就会)
  9. SQL Server DATEPART() 函数
  10. 【mmdetection3d】——学习配置文件
  11. chrome源代码下载 编译 linux,源代码编译chrome os
  12. 完结!视频课程:CMOS模拟集成电路设计
  13. 双指缩放canvas图片_JS实现移动端双指缩放和旋转方法
  14. 制造业执行系统MES 在汽车零配件行业展露锋芒
  15. vasp能装在window系统里吗_Window安装系统详解
  16. 虾皮API接口—获取商品详情
  17. A ConvNet for the 2020s
  18. 【状语从句练习题】连词 + 过去分词
  19. Uniswap V3流动资金池遭遇网络钓鱼攻击,已损失价值3278ETH的NFT头寸,约合3563644美元。
  20. 手把手教你实现聚光灯效果

热门文章

  1. ORA-03001,GATHER_TABLE_STATS数据库自动收集统计信息报错
  2. java并发编程系列-内存模型基础
  3. Windows 下的 7 种 DLL 劫持技术
  4. 学习AI可能不需要那么多数学知识:20小时进阶计划
  5. 折衷的方式实现php与ruby共享session实现单点登录
  6. 交换机生成树协议配置
  7. ThinkPHP源码学习 data_to_xml函数 数据转成xml格式
  8. 11G中自动收集统计信息
  9. C++ socket编程
  10. android应用植入广告SDK,获取广告收入