java线程API

2023-11-19

守护线程

守护线程也称为:后台线程

  • 守护线程是通过普通线程调用setDaemon(boolean on)方法设置而来的,因此创建上与普通线程无 异.
  • 守护线程的结束时机上有一点与普通线程不同,即:进程的结束.
  • 进程结束:当一个进程中的所有普通线程都结束时,进程就会结束,此时会杀掉所有正在运行的守护线 程.
/**
* 守护线程
* 守护线程是通过普通线程调用setDaemon(true)设置而转变的。因此守护线程创建上
* 与普通线程无异。
* 但是结束时机上有一点不同:进程结束。
* 当一个java进程中的所有普通线程都结束时,该进程就会结束,此时会强制杀死所有正在
* 运行的守护线程。
*/
public class DaemonThreadDemo {
    public static void main(String[] args) {
        Thread rose = new Thread(){
            public void run(){
                for(int i=0;i<5;i++){
                    System.out.println("rose:let me go!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                }
                System.out.println("rose:啊啊啊啊啊啊AAAAAAAaaaaa....");
                System.out.println("噗通");
            }
        };


        Thread jack = new Thread(){
            public void run(){
                while(true){
                    System.out.println("jack:you jump!i jump!");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                }
            }
        };

        rose.start();
        jack.setDaemon(true);//设置守护线程必须在线程启动前进行
        jack.start();
    }
}

通常当我们不关心某个线程的任务什么时候停下来,它可以一直运行,但是程序主要的工作都结束时它应当 跟着结束时,这样的任务就适合放在守护线程上执行.比如GC就是在守护线程上运行的.

多线程并发安全问题

当多个线程并发操作同一临界资源,由于线程切换时机不确定,导致操作临界资源的顺序出现混乱严重时可能导 致系统瘫痪.

临界资源:操作该资源的全过程同时只能被单个线程完成.

/**
* 多线程并发安全问题
* 当多个线程并发操作同一临界资源,由于线程切换的时机不确定,导致操作顺序出现
* 混乱,严重时可能导致系统瘫痪。
* 临界资源:同时只能被单一线程访问操作过程的资源。
*/
public class SyncDemo {
    public static void main(String[] args) {
        Table table = new Table();
        Thread t1 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();
                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };

        Thread t2 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();

                    /*
                        static void yield()
                        线程提供的这个静态方法作用是让执行该方法的线程
                        主动放弃本次时间片。
                        这里使用它的目的是模拟执行到这里CPU没有时间了,发生
                        线程切换,来看并发安全问题的产生。
                    */

                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };

        t1.start();
        t2.start();
    }
}

class Table{
    private int beans = 20;//桌子上有20个豆子
    public int getBean(){
        if(beans==0){
            throw new RuntimeException("没有豆子了!");
        }
        Thread.yield();
        return beans--;
    }
}

synchronized关键字

synchronized有两种使用方式

  • 在方法上修饰,此时该方法变为一个同步方法
  • 同步块,可以更准确的锁定需要排队的代码片段

同步方法

当一个方法使用synchronized修饰后,这个方法称为"同步方法",即:多个线程不能同时 在方法内部执行.只 能有先后顺序的一个一个进行. 将并发操作同一临界资源的过程改为同步执行就可以有效的解决并发安全 问题.

/**
* 多线程并发安全问题
* 当多个线程并发操作同一临界资源,由于线程切换的时机不确定,导致操作顺序出现
* 混乱,严重时可能导致系统瘫痪。
* 临界资源:同时只能被单一线程访问操作过程的资源。
*/
public class SyncDemo {
    public static void main(String[] args) {
        Table table = new Table();

        Thread t1 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();
                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };

        Thread t2 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();

                    /*
                    static void yield()
                    线程提供的这个静态方法作用是让执行该方法的线程
                    主动放弃本次时间片。
                    这里使用它的目的是模拟执行到这里CPU没有时间了,发生
                    线程切换,来看并发安全问题的产生。
                    */

                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };

        t1.start();
        t2.start();

    }
}

class Table{
    private int beans = 20;//桌子上有20个豆子

    /**
        * 当一个方法使用synchronized修饰后,这个方法称为同步方法,多个线程不能
        * 同时执行该方法。
        * 将多个线程并发操作临界资源的过程改为同步操作就可以有效的解决多线程并发
        * 安全问题。
        * 相当于让多个线程从原来的抢着操作改为排队操作。
    */

     public synchronized int getBean(){

        if(beans==0){
            throw new RuntimeException("没有豆子了!");
        }

        Thread.yield();
        return beans--;
    }
}

同步块

有效的缩小同步范围可以在保证并发安全的前提下尽可能的提高并发效率.同步块可以更准确的控制需要 多个线程排队执行的代码片段.

语法:

synchronized(同步监视器对象){
    需要多线程同步执行的代码片段
}

同步监视器对象即上锁的对象,要想保证同步块中的代码被多个线程同步运行,则要求多个线程看到的同步 监视器对象是同一个.

/**
* 有效的缩小同步范围可以在保证并发安全的前提下尽可能提高并发效率。
*
* 同步块
* 语法:
* synchronized(同步监视器对象){
* 需要多个线程同步执行的代码片段
* }
* 同步块可以更准确的锁定需要多个线程同步执行的代码片段来有效缩小排队范围。
*/
public class SyncDemo2 {
    public static void main(String[] args) {
        Shop shop = new Shop();
        Thread t1 = new Thread(){
            public void run(){
                shop.buy();
            }
        };

        Thread t2 = new Thread(){
            public void run(){
                shop.buy();
            }
        };

        t1.start();
        t2.start();
    }
}

class Shop{
    public void buy(){
        /*
            在方法上使用synchronized,那么同步监视器对象就是this。
        */
        // public synchronized void buy(){
        Thread t = Thread.currentThread();//获取运行该方法的线程
        try {
            System.out.println(t.getName()+":正在挑衣服...");
            Thread.sleep(5000);
            /*
                使用同步块需要指定同步监视器对象,即:上锁的对象
                这个对象可以是java中任何引用类型的实例,只要保证多个需要排队
                执行该同步块中代码的线程看到的该对象是"同一个"即可
            */

            synchronized (this) {
            // synchronized (new Object()) {//没有效果!
                System.out.println(t.getName() + ":正在试衣服...");
                Thread.sleep(5000);
            }

            System.out.println(t.getName()+":结账离开");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

互斥锁

当多个线程执行不同的代码片段,但是这些代码片段之间不能同时运行时就要设置为互斥的.

使用synchronized锁定多个代码片段,并且指定的同步监视器是同一个时,这些代码片段之间就是互斥的.

/**
* 互斥锁
* 当使用synchronized锁定多个不同的代码片段,并且指定的同步监视器对象相同时,
* 这些代码片段之间就是互斥的,即:多个线程不能同时访问这些方法。
*/
public class SyncDemo4 {
    public static void main(String[] args) {
        Foo foo = new Foo();
        Thread t1 = new Thread(){
            public void run(){
                foo.methodA();
            }
        };

        Thread t2 = new Thread(){
            public void run(){
                foo.methodB();
            }
        };

        t1.start();
        t2.start();
    }
}

class Foo{
    public synchronized void methodA(){
        Thread t = Thread.currentThread();

        try {
            System.out.println(t.getName()+":正在执行A方法...");
            Thread.sleep(5000);
            System.out.println(t.getName()+":执行A方法完毕!");

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void methodB(){
        Thread t = Thread.currentThread();

        try {
            System.out.println(t.getName()+":正在执行B方法...");
            Thread.sleep(5000);
            System.out.println(t.getName()+":执行B方法完毕!");

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

总结

守护线程与普通线程的区别:守护线程是通过普通线程调用setDaemon(true)设置而来的

主要区别体现在当java进程中所有的普通线程都结束时进程会结束,在结束前会杀死所有还在运行的守 护线程

重点:多线程并发安全问题。

  • 什么是多线程并发安全问题:

        当多个线程并发操作同一临界资源,由于线程切换时机不确定,导致执行顺序出现混乱。 解决办法:

        将并发操作改为同步操作就可有效的解决多线程并发安全问题

  • 同步与异步的概念:同步和异步都是说的多线程的执行方式。

        多线程各自执行各自的就是异步执行,而多线程执行出现了先后顺序进行就是同步执行

  • synchronized的两种用法

        1.直接在方法上声明,此时该方法称为同步方法,同步方法同时只能被一个线程执行

        2.同步块,推荐使用。同步块可以更准确的控制需要同步执行的代码片段。

        有效的缩小同步范围可以在保证并发安全的前提下提高并发效率

  • 互斥性

        当使用多个synchronized修饰了多个代码片段,并且指定的同步监视器都是同一个对象时,这些代 码片段就是互斥的,多个线程不能同时在这些代码片段上执行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java线程API 的相关文章

  • 如果测试用例失败,Selenium Web 驱动程序无法关闭 Firefox 实例

    我各位 我正在使用 junit 和 selenium web 驱动程序 2 28 问题是 如果我运行成功的测试用例 Web 驱动器能够关闭 Firefox 实例 但是当测试用例失败时 Selenium Web 驱动器无法关闭 Firefox
  • 如何在 JFace 的 TableViewer 中创建复选框?

    我创建了一个包含两列的 tableViewer 我想将其中一列设为复选框 为此 我创建了一个 CheckBoxCellEditor 但我不知道为什么它不起作用 名为 tableName 的列显示其值正常 色谱柱规格如下 String COL
  • 线程自动利用多个CPU核心?

    假设我的应用程序运行 2 个线程 例如渲染线程和游戏更新线程 如果它在具有多核 CPU 当今典型 的移动设备上运行 我是否可以期望线程在可能的情况下自动分配给不同的核心 我知道底层操作系统内核 Android linux内核 决定调度 我的
  • Java8无符号算术

    据广泛报道 Java 8 具有对无符号整数的库支持 然而 似乎没有文章解释如何使用它以及有多少可能 有些函数 例如 Integer CompareUnsigned 很容易找到 并且似乎可以实现人们所期望的功能 但是 我什至无法编写一个简单的
  • 在浏览器中点击应用程序时播放框架挂起

    我正在 Play 中运行一个应用程序activator run 也许 5 次中有 3 次 它会挂起 当我去http localhost 9000 它就永远坐在那里旋转 我看到很多promise timed out错误也 我应该去哪里寻找这个
  • java.io.IOException: %1 不是有效的 Win32 应用程序

    我正在尝试对 XML 文档进行数字签名 为此我有两个选择 有一个由爱沙尼亚认证中心为程序员创建的库 还有一个由银行制作的运行 Java 代码的脚本 如果使用官方 认证中心 库 那么一切都会像魅力一样进行一些调整 但是当涉及到银行脚本时 它会
  • Convert.FromBase64String 方法的 Java 等效项

    Java 中是否有相当于Convert FromBase64String http msdn microsoft com en us library system convert frombase64string aspx which 将指
  • HDFS:使用 Java / Scala API 移动多个文件

    我需要使用 Java Scala 程序移动 HDFS 中对应于给定正则表达式的多个文件 例如 我必须移动所有名称为 xml从文件夹a到文件夹b 使用 shell 命令我可以使用以下命令 bin hdfs dfs mv a xml b 我可以
  • 迁移到 java 17 后有关“每个进程的内存映射”和 JVM 崩溃的 GC 警告

    我们正在将 java 8 应用程序迁移到 java 17 并将 GC 从G1GC to ZGC 我们的应用程序作为容器运行 这两个基础映像之间的唯一区别是 java 的版本 例如对于 java 17 版本 FROM ubuntu 20 04
  • Clip 在 Java 中播放 WAV 文件时出现严重延迟

    我编写了一段代码来读取 WAV 文件 大小约为 80 mb 并播放该文件 问题是声音播放效果很差 极度滞后 你能告诉我有什么问题吗 这是我的代码 我称之为doPlayJframe 构造函数内的函数 private void doPlay f
  • Java中接口作为方法参数

    前几天去面试 被问到了这样的问题 问 反转链表 给出以下代码 public class ReverseList interface NodeList int getItem NodeList nextNode void reverse No
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序
  • 制作java包

    我的 Java 类组织变得有点混乱 所以我要回顾一下我在 Java 学习中跳过的东西 类路径 我无法安静地将心爱的类编译到我为它们创建的包中 这是我的文件夹层次结构 com david Greet java greeter SayHello
  • 检查 protobuf 消息 - 如何按名称获取字段值?

    我似乎无法找到一种方法来验证 protobuf 消息中字段的值 而无需显式调用其 getter 我看到周围的例子使用Descriptors FieldDescriptor实例到达消息映射内部 但它们要么基于迭代器 要么由字段号驱动 一旦我有
  • 应用程序关闭时的倒计时问题

    我制作了一个 CountDownTimer 代码 我希望 CountDownTimer 在完成时重新启动 即使应用程序已关闭 但它仅在应用程序正在运行或重新启动应用程序时重新启动 因此 如果我在倒计时为 00 10 分钟 秒 时关闭应用程序
  • 使用 SAX 进行 XML 解析 |如何处理特殊字符?

    我们有一个 JAVA 应用程序 可以从 SAP 系统中提取数据 解析数据并呈现给用户 使用 SAP JCo 连接器提取数据 最近我们抛出了一个异常 org xml sax SAXParseException 字符引用 是无效的 XML 字符
  • 运行 Jar 文件时出现问题

    我已将 java 项目编译成 Jar 文件 但运行它时遇到问题 当我跑步时 java jar myJar jar 我收到以下错误 Could not find the main class myClass 类文件不在 jar 的根目录中 因
  • Keycloak - 自定义 SPI 未出现在列表中

    我为我的 keycloak 服务器制作了一个自定义 SPI 现在我必须在管理控制台上配置它 我将 SPI 添加为模块 并手动安装 因此我将其放在 module package name main 中 并包含 module xml 我还将其放
  • Android JNI C 简单追加函数

    我想制作一个简单的函数 返回两个字符串的值 基本上 java public native String getAppendedString String name c jstring Java com example hellojni He
  • android Accessibility-service 突然停止触发事件

    我有一个 AccessibilityService 工作正常 但由于开发过程中的某些原因它停止工作 我似乎找不到这个原因 请看一下我的代码并告诉我为什么它不起作用 public class MyServicee extends Access

随机推荐