【Java篇】多线程详解-程序员宅基地

技术标签: java  开发语言  

【Java】多线程基础详解


线程的相关概念

  • 程序:程序是含有指令和数据的文件,也可以说程序是静态代码,被存储在磁盘或者其他的数据存储设备中。
  • 进程:进程是程序执行一次的过程。进程是系统运行程序的单位,因此进程是动态的。当程序运行时就会被系统载入内存,并且启动他的工作。对于完全不相关的程序,在同时执行时,不会做数据的交换,而且可以完全独立运行。
  • 多任务:多任务是在一个系统中可以同时运行多个进程。每个进程都是独立的任务,每个进程都有自己独立的内存。所谓的同时运行进程,其实是操作系统将资源分配给各个进程以后,每个进程在CPU上交替运行。
  • 线程:线程是比进程更小的执行单位。一个进程执行过程可以产生多个线程,形成多条执行路径,提高了运行效率。不同的是,同类的多个线程共享同一块内存,在进行各个线程的切换时开销比进程小很多。
  • 多线程:同时执行一个以上的线程,一个线程的执行不必等到另一个线程执行完成在执行。

提示:以下是本篇文章正文内容,下面案例可供参考

一、创建线程的几种方式

1. 继承Thread类

  • Thread 也是实现Runnable接口
  • 管理线程的生命周期

2. 实现Runnable接口

  • 只有一个run方法

3.实现Callable接口

  • 只有一个call方法带有返回值

4. 推荐使用Runnable接口

  • extends 只能继承一个类 单继承
  • implements 可以实现多个接口 灵活
  • 继承Thread的类创建的对象 只能调用一次start 方法启动线程
public class ThreadTest{
    

    public static void main(String[] args){
    
        
         RunTest r1 = new RunTest ();
         Thread t2 = new Thread (r1);
         Thread t3 = new Thread (r1);

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

         try {
    
         t3.join ();
         t2.join ();
         } catch (InterruptedException e) {
    
         throw new RuntimeException (e);
         }

         System.out.println (r1.t);


    }
}

class RunTest implements Runnable{
    
    int t;
    Object o1 = new Object ();

    @Override
    public void run(){
    
        // 保证原子性
        synchronized (o1) {
    
            for(int i = 0; i < 10000; i++){
    
                t++;
            }
        }
    }
}

二、线程安全

1. 线程安全问题引入

  • 对于一个变量的操作: 使用 赋值 读取 写入 加载 上锁 解锁
  • 多个线程同时操作同一个变量:就会因为内存中原子操作不及时等原因导致重复(非同步操作)操作

2.解决线程安全问题

  • 保证对于这个共享资源的操作必须是原子操作
  • 对资源加锁,操作完成之后释放锁
    • synchronized 关键字
      • 隐式锁 加锁与解锁 不可代码操作的
    • Lock接口下的锁
      • 显式锁 主动的加锁 与 解锁
        • lock
        • unlock
  • 在锁块中的代码如果出现了异常中断,卡住
    • 导致此资源不能被释放,一直被当前线程占用
    • 显式锁: 如果出现了异常,可以在finally块中主动的释放资源

3. 线程中的可见性问题:

  • 一个线程把资源修改了
  • 其他线程无法即时得知

(示例):对于两个线程 t1 和 t2, 用 t2 线程来控制 t1 线程的关闭;
代码如下:

public class ThreadTest{
    

    public static void main(String[] args){
    

        Thread1 t1= new Thread1 ();
        Thread2 t2= new Thread2 (t1);
        t1.start ();

        try {
    
            Thread.sleep (2000);
        } catch (InterruptedException e) {
    
            throw new RuntimeException (e);
        }
        t2.start ();

    }
}


class Thread1 extends Thread{
    
    boolean flag = true;

    @Override
    public void run(){
    

        System.out.println ("Thread1 启动了...");
        int num=0;
        while(flag){
    
            num++;
        }
        System.out.println ("Thread1 结束了...");
    }
}

class Thread2 extends Thread{
    
    Thread1 t1;

    Thread2(Thread1 t1){
    
        this.t1 = t1;
    }

    @Override
    public void run(){
    

        System.out.println ("Thread2 启动了...");
        t1.flag = false;
        System.out.println (" t1.flag = false; \n Thread2 结束了...");
    }
}

运行结果显示

t2 进程结束了,t1 进程还未结束

在这里插入图片描述

解决方法

用volatile关键字 保证线程间通信即时 (不能作为原子操作的标准)
代码如下:

public class ThreadTest{
    

  public static void main(String[] args){
    

    Thread1 t1= new Thread1 ();
    Thread2 t2= new Thread2 (t1);
    t1.start ();

    try {
    
      Thread.sleep (2000);
    } catch (InterruptedException e) {
    
      throw new RuntimeException (e);
    }
    t2.start ();
    
  }
}

class Thread1 extends Thread{
    
  volatile boolean flag = true;

  @Override
  public void run(){
    

    System.out.println ("Thread1 启动了...");
    int num=0;
    while(flag){
    
      num++;
    }
    System.out.println ("Thread1 结束了...");
  }
}

class Thread2 extends Thread{
    
  Thread1 t1;

  Thread2(Thread1 t1){
    
    this.t1 = t1;
  }

  @Override
  public void run(){
    

    System.out.println ("Thread2 启动了...");
    t1.flag = false;
    System.out.println (" t1.flag = false; \n Thread2 结束了...");
  }
}

运行结果显示

t2进程结束后,t1进程也结束了。

运行结果

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Kingharbor/article/details/125622340

智能推荐

python绘制三维网格图_使用python绘制三维圆柱网格模型图——voxels函数的使用-程序员宅基地

文章浏览阅读1k次。最近接到老师的新任务——画一个XXX的三维模型图,和师兄交流后大概知道了要做什么,在师兄的建议下成功入了python的坑。然而网上查了很长时间才在matplotlib的example中找到了这种画圆柱网格的模型图的实例。实例import matplotlib.pyplot as pltimport matplotlib.colorsimport numpy as npfrom mpl_toolki..._ax.voxels

Semaphore的注意点_semphore 报错interrupter null-程序员宅基地

文章浏览阅读349次。seamphore大家玩的都比较多,使用起来也很简单,获取令牌和释放,但是其中坑却不少,而且会让人很难发现,希望能通俗易懂的小例子讲明白其中的几个道理。一、线程都被阻塞了?public class demo2 { static Semaphore semaphore = new Semaphore(1); public static void method1() { try { System.out.println(Thread.curr.._semphore 报错interrupter null

第9关:表单元素——文本域_第9关:表单元素——文本域-程序员宅基地

文章浏览阅读291次。表单元素——文本域_第9关:表单元素——文本域

上海人社APP历年社保查询攻略-程序员宅基地

文章浏览阅读2.7k次。随时随地查社保,太方便了,快来收藏起来!!!1、苹果商店或安卓商店下载【上海人社app】2、账号登录,账号:身份证号码 密码:去社保中心开通3、首页,点击CA证书管理4、点击【CA证书申..._上海人社app怎么查社保缴费记录

详解Xcode 7的视图调试_xcode视图-程序员宅基地

文章浏览阅读2.1k次。http://www.cocoachina.com/ios/20150423/11658.html本文由远的风景翻译自raywenderlich,作者:Scott Berrevoets原文:View Debugging in Xcode 6开发者会经常遇到视图或者Auto Layout约束中存在bug的情况,并且这种bug很难通过代码发现,所以开发者很有必要熟知如何进行_xcode视图

vue+h5做的App使用api进行文件的下载自动安装打开_h5+vue实现apk下载并自动打开-程序员宅基地

文章浏览阅读5.1k次。 本人第一次写博客,菜鸟一只,也不大会用语言表述,写博客只是单纯记录下自己遇到的问题,并且记录下来以便日后使用的时候可以有个思路。如果能够帮助到别人就更好了。 现在公司的项目需要用vue做一个安卓app,需要实现app的自动更新功能。我的设计方案就是打开App先提交请求到后台,需要更新会返回下载地址。创建下载的代码: // 下载最新版本 JX_do..._h5+vue实现apk下载并自动打开

随便推点

如何在 Windows10 下运行 Tensorflow 的目标检测?_win10 tensorflow-程序员宅基地

文章浏览阅读1.1k次。看过很多博主通过 Object Detection 实现了一些皮卡丘捕捉,二维码检测等诸多特定项的目标检测。而我跟着他们的案例来运行的时候,不是 Tensorflow 版本冲突,就是缺少什么包,还有是运行官方 object_detection_tutorial 不展示图片等等问题。在看过一个国外博主例子,我也通过 Tensorflow-GPU1.10.0 运行了官方例子,既然要使用 GPU 则需要把 CUDA 先配置好,上一篇文章有特别详细介绍到。而这里就捋一下在运行过程遇到的种种问题。_win10 tensorflow

Vue3.0(四):Composition API的使用_vue3 composition-程序员宅基地

文章浏览阅读2.3k次,点赞53次,收藏43次。定义普通函数setup(){//可以直接使用,但不是响应式return{message定义响应式数据(reactive定义复杂数据:对象/数组等,不能传入普通类型的,比如字符串等在option api中data中定义的数据实际上就是交给了reactive函数setup(){//此时就是响应式了a:100,b:200})//对obj进行修改return{obj定义响应式数据(ref):返回的是ref对象,需要使用.value进行获取值定义简单类型的响应式数据。_vue3 composition

【Linux】 通过 Xmanager 连接到Linux 虚拟机上_xmanager 百度网盘-程序员宅基地

文章浏览阅读1.3k次。一 获取xmanager我们可以在官网上下载最新版本的 xmanager 官网地址我这里也提供了一款比较老版本的 xmanager 自用感觉很不错百度网盘链接提取码 v8m7 自行解压里面已有机器码二 创建会话创建基本连接属性1 点击黄色 + 号 打开会话窗口2 点击新建按钮 打开新建会话属性3 输入名称 (这个名称最好与你的机器host域名匹配)4 输入主机IP地址5 点击确定按钮完成设置第四步的IP地址如何查看进入自己的 vmware 虚..._xmanager 百度网盘

上百例大数据可视化三维GIS可视化数据产品,非常漂亮的设计,大数据可视化,三维GIS可视化,这才是大前端,产品、设计、GIS、开发、架构都需要好好看看_大数据推送给三维前端-程序员宅基地

文章浏览阅读1.6w次,点赞6次,收藏15次。上百例大数据可视化三维GIS可视化数据产品,非常漂亮的设计,大数据可视化,三维GIS可视化,这才是大前端欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入随着互联网的发展,各项技术的不断成熟,数_大数据推送给三维前端

python循环语句打印矩形_Python 循环语句之 while,for语句详解-程序员宅基地

文章浏览阅读1k次。下面为大家分享一篇Python 循环语句之 while,for语句详解,具有很好的参考价值,希望对大家有所帮助。一起过来看看吧Python中有两种循环,分别为:for循环和while循环。 for循环可以遍历任何序列的项目,如一个列表或者一个字符串。while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务。循环语句(有两种):while 语句for 语句w..._用for while循环嵌套输出长方形

c#串口编程(傻瓜教程,手把手教你学会)_c# 串口编程-程序员宅基地

文章浏览阅读5.4w次,点赞249次,收藏1.1k次。在单片机项目开发中,上位机也是一个很重要的部分,主要用于数据显示(波形、温度等)、用户控制(LED,继电器等),下位机(单片机)与 上位机之间要进行数据通信的两种方式都是基于串口的:USB转串口 —— 上位机和下位机通过USB转串口连接线直接相连进行数据交互; 串口转WIFI(ESP8266) —— 上位机和下位机基于TCP/IP协议通过WIFI传输数据; 串口转蓝牙(HC-06)—— 不多用,暂不介绍;上位机软软件开发主要包括以下两种:  1、Windows上位机(EXE可执行程序)._c# 串口编程