死锁_线程池

线程池自引发死锁 线程池自引发死锁 死锁是由许多线程锁定相同资源引起的 如果在该池中运行的任务内使用线程池,也会发生死锁 像RxJava / Reactor这样的现代图书馆也很容易受到影响 死锁是两个或多个线程正在等待彼此获取的资源的情况。例如,线程A等待lock1线程B锁定,而线程B等待lock2,由线程A锁定。在最坏的情况下,应用程序冻结无限期的时间。让我向您展示一个具体的例子。想象一下,有一个Lumberjack类可以保存对两个附件锁的引用: import com.google.common.colle 阅读详情

Lock锁

概述:

​ 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是并不能直观看到线程在哪里获取了锁,在哪里释放了锁,所以为了更清晰的展示如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock,可以使用此对象,来表示锁的创建和释放。

特点:

  • Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
  • 同步代码块、同步方法、以及Lock锁的默认创建方式都是非公平情况
  • 再创建Lock锁对象时,可以将参数传递true,那么该锁就变为一个公平锁,一旦变为公平锁之后,每个线程都有被执行的机会。

构造方法:ReentrantLock():创建一个ReentrantLock的实例

加锁解锁方法:

  • void lock() :获得锁
  • void unlock():释放锁

例:卖火车票:
需求:
模拟火车站卖票方式,完成如下需求:
(1)定义三个窗口,模拟三个窗口同时售卖一百张火车票,在卖票之后,在控制台 展示卖票结果,当第100张票卖出后,结束程序即可。
(2)比如:
窗口1卖出一张票,还剩99张票
窗口1卖出一张票,还剩98张票
窗口3卖出一张票,还剩97张票
窗口2卖出一张票,还剩96张票
……
窗口1卖出一张票,还剩0张票

public class homework01 {
    static  int tic = 100;
    public static void main(String[] args) {
        Runnable r =new Runnable() {
            //创建锁对象,布尔值为true的时候是代表一个公平锁,每个线程都有机会执行
            ReentrantLock reen = new ReentrantLock(true);
            @Override
            public void run() {
                while (true) {
                    try{
                        //获取锁对象
                        reen.lock();
                        if (tic < 1) return;
                        tic = tic - 1;
                        System.out.println(Thread.currentThread().getName() + "卖出一张票,还剩" + tic + "张票");
                    }finally {
                        //释放锁对象
                        reen.unlock();
                    }

                }
            }
        };
            Thread t1 = new Thread(r, "窗口1");
            Thread t2 = new Thread(r, "窗口2");
            Thread t3 = new Thread(r, "窗口3");
            t1.start();
            t2.start();
            t3.start();
    }
}

死锁

死锁概述:

​ 线程死锁是指由两个或者多个线程互相持有并且需要对方的的资源(锁),导致这些线 程处于等待状态,无法前往执行

问题:

  • 线程A:需要获取到锁x以及锁y 线程A获取到x锁,需要锁y才可以执行
  • 线程B:需要获取到锁x以及锁y 线程B获取到y锁,需要锁x才可以执行

解决:

可以让线程A和线程B先抢同一支筷子,拿到第一支筷子的线程,才能获取第二支筷 子。如果线程第一支筷子没有拿到,没有机会拿第二支筷子

图示:

Lock锁

概述:

​ 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是并不能直观看到线程在哪里获取了锁,在哪里释放了锁,所以为了更清晰的展示如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock,可以使用此对象,来表示锁的创建和释放。

特点:

  • Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
  • 同步代码块、同步方法、以及Lock锁的默认创建方式都是非公平情况
  • 再创建Lock锁对象时,可以将参数传递true,那么该锁就变为一个公平锁,一旦变为公平锁之后,每个线程都有被执行的机会。

构造方法:ReentrantLock():创建一个ReentrantLock的实例

加锁解锁方法:

  • void lock() :获得锁
  • void unlock():释放锁

例:卖火车票:
需求:
模拟火车站卖票方式,完成如下需求:
(1)定义三个窗口,模拟三个窗口同时售卖一百张火车票,在卖票之后,在控制台 展示卖票结果,当第100张票卖出后,结束程序即可。
(2)比如:
窗口1卖出一张票,还剩99张票
窗口1卖出一张票,还剩98张票
窗口3卖出一张票,还剩97张票
窗口2卖出一张票,还剩96张票
……
窗口1卖出一张票,还剩0张票

public class homework01 {
    static  int tic = 100;
    public static void main(String[] args) {
        Runnable r =new Runnable() {
            //创建锁对象,布尔值为true的时候是代表一个公平锁,每个线程都有机会执行
            ReentrantLock reen = new ReentrantLock(true);
            @Override
            public void run() {
                while (true) {
                    try{
                        //获取锁对象
                        reen.lock();
                        if (tic < 1) return;
                        tic = tic - 1;
                        System.out.println(Thread.currentThread().getName() + "卖出一张票,还剩" + tic + "张票");
                    }finally {
                        //释放锁对象
                        reen.unlock();
                    }

                }
            }
        };
            Thread t1 = new Thread(r, "窗口1");
            Thread t2 = new Thread(r, "窗口2");
            Thread t3 = new Thread(r, "窗口3");
            t1.start();
            t2.start();
            t3.start();
    }
}

死锁

死锁概述:

​ 线程死锁是指由两个或者多个线程互相持有并且需要对方的的资源(锁),导致这些线 程处于等待状态,无法前往执行

问题:

  • 线程A:需要获取到锁x以及锁y 线程A获取到x锁,需要锁y才可以执行
  • 线程B:需要获取到锁x以及锁y 线程B获取到y锁,需要锁x才可以执行

解决:

可以让线程A和线程B先抢同一支筷子,拿到第一支筷子的线程,才能获取第二支筷 子。如果线程第一支筷子没有拿到,没有机会拿第二支筷子

图示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8x8n98A7-1646963480445)(C:\Users\12994\Desktop\笔记整理\21_死锁_线程池_单例.assets\wps5CB7.tmp.jpg)]

代码:

public static void main(String[] args) throws InterruptedException {
    String s1 = "左筷子";
    String s2 = "右筷子";
    Thread th1 =new Thread(){
        @Override
        public void run() {
            synchronized (s1){
                System.out.println("A拿到了"+s1+",等待"+s2);
                synchronized (s2){
                    System.out.println("A都拿到了,可以吃饭");
                }
            }
        }
    };
    Thread th2 = new Thread(){
        @Override
        public void run() {
            synchronized (s2){
                System.out.println("B拿到了"+s2+",等待"+s1);
                synchronized (s1){
                    System.out.println("B都拿到了,可以吃饭");
                }
            }
        }
    };
    th1.start();
    th2.start();
}

线程的生命周期

线程从创建到销毁的过程就是线程的生命周期

再线程的生命周期中有很多状态的描述

线程生命周期中的状态

  • 新建态:线程对象刚创建好的状态

  • 就绪态:线程启动之后,等待cpu来执行的状态

  • 运行态:正在被cpu执行的状态

  • 阻塞态:即使cpu来执行该线程,该线程也无法执行的状态

    ​ 等待锁 线程休眠 IO数据

  • 死亡态(消亡):线程正常将任务执行完成,或者碰到异常意外销毁

线程状态之间的关系:

在这里插入图片描述

获取线程的状态

以上所说的线程的状态,都是理论分析的状态,如果需要在代码中获取线程的状态,可以获取。

获取线程状态的方法:getState()

特点:该方法的返回值是Thread类中的内部类:State,该类型是一个枚举类,该类中定义了六个对象,来表示线程的六种状态对象。

罗列:

  • NEW:新建态
  • RUNNABLE:就绪态或者运行态
  • BLOCKED:阻塞态 IO数据导致的阻塞
  • WAITING:阻塞态 wait方法导致的阻塞
  • TIMED_WAITING:阻塞态 sleep方法导致的阻塞态
  • TERMINATED:死亡态
public static void main(String[] args) {
    Thread t = new Thread(){
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println("----");
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    //获取线程状态:新建态
    Thread.State s = t.getState();
    System.out.println(s);
    //获取线程状态:可能是就绪或者运行态、阻塞态、死亡态
    t.start();
    Thread.State s1 = t.getState();
    System.out.println(s1);
}

线程池

概述:用来存储线程的一个容器

使用线程池的原因:

  • 如果Java语言不支持线程池:

    • 想要使用新线程完成任务,自己创建一个线程对象,将任务对象提交给线程对象,启动线程,完成任务,当任务完成之后,该线程对象就会被销毁。如果程序种有很多任务,就需要花费很多的时间在线程的创建和销毁上,就降低了程序的运行效率。反复的对线程创建和销毁造成了资源的浪费。

    • 如果某条线程在执行任务的过程中,该线程被意外销毁了,那么就导致任务无法完成。

  • 如果Java语言提供了线程池:

    • 想要完成多个任务,不需要自己新创建线程对象,直接从线程池种获取线程来完成任务,解决创建线程对象的时间;当线程池种的线程完成任务之后,将该线程对象回收到线程池种,以后可以反复使用,避免了资源的浪费;如果线程池种的线程在完成任务的过程种被意外销毁,如果被销毁,线程池会继续分配线程完成该任务。

线程池的使用

步骤:

  • 获取线程池对象
  • 创建任务类对象
  • 将任务对象提交给线程池
  • 关闭线程池对象

获取线程池对象:

  • Executors:工具类获取线程池的工具类
  • newSingleThreadExecutor() :获取一个具有单个线程的线程池对象
  • newFixedThreadPool(int n) :获取一个有n条线程的线程池对象
  • newCachedThreadPool() :获取一个线程池对象,根据提交的任务分配线程

将任务提交给线程池对象:

submit(Runnable r);

  • 如果线程池种的线程少,任务多;存在的线程先并发完成任务,那一条线程先完成任务,就继续做等待的任务。

  • 如果线程池种线程多,任务少:首先随机分配线程去并发完成提交的任务,多余的线程等待任务的提交。

private static void test02() {
    //获取一个线程池对象:并指定线程池中的线程条数
    //-------当线程数量多余任务数的时候,有的不执行
    //-------当线程数量少于任务书的时候,先执行完的线程在执行没被执行的任务
    ExecutorService three = Executors.newFixedThreadPool(4);

    Runnable r1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("任务1-----"+Thread.currentThread().getName());
        }
    };

    Runnable r2 = new Runnable() {
        @Override
        public void run() {
            System.out.println("任务2-----"+Thread.currentThread().getName());
        }
    };
    Runnable r3 = new Runnable() {
        @Override
        public void run() {
            System.out.println("任务3-----"+Thread.currentThread().getName());
        }
    };

    //把任务提交线程
    three.submit(r1);
    three.submit(r2);
    three.submit(r3);
    //关闭线程池,关闭之后不能再继续提交任务
    three.shutdown();
}
  • 如果线程池中线程和任务一样多,线程之间并发完成任务。
//获取一个线程池对象:不指定线程数量,根据任务数量自动为其分配
        ExecutorService es = Executors.newCachedThreadPool();
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("任务1-----"+Thread.currentThread().getName());
            }
        };

        Runnable r2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("任务2-----"+Thread.currentThread().getName());
            }
        };
     

        es.submit(r1);
        es.submit(r2);
        //关闭线程池,关闭之后不能再继续提交任务
        es.shutdown();

关闭线程池的方法:

  • shutdown() :将已经提交的任务全部完成之后,再关闭线程池。关闭后,不能再提交
  • shutdownNow() :将正在运行的任务完成之后,关闭线程池。已经提交还没运行的任务,不再运行。
//把任务提交线程池,但是线程池中只有两个线程
three.submit(r1);
three.submit(r2);
three.submit(r3);
//关闭线程池,关闭之后不能再继续提交任务
three.shutdown();
//关闭后,r3任务也还没有运行
three.shutdownNow();

代码:

public static void main(String[] args) throws InterruptedException {
    String s1 = "左筷子";
    String s2 = "右筷子";
    Thread th1 =new Thread(){
        @Override
        public void run() {
            synchronized (s1){
                System.out.println("A拿到了"+s1+",等待"+s2);
                synchronized (s2){
                    System.out.println("A都拿到了,可以吃饭");
                }
            }
        }
    };
    Thread th2 = new Thread(){
        @Override
        public void run() {
            synchronized (s2){
                System.out.println("B拿到了"+s2+",等待"+s1);
                synchronized (s1){
                    System.out.println("B都拿到了,可以吃饭");
                }
            }
        }
    };
    th1.start();
    th2.start();
}

线程的生命周期

线程从创建到销毁的过程就是线程的生命周期

再线程的生命周期中有很多状态的描述

线程生命周期中的状态

  • 新建态:线程对象刚创建好的状态

  • 就绪态:线程启动之后,等待cpu来执行的状态

  • 运行态:正在被cpu执行的状态

  • 阻塞态:即使cpu来执行该线程,该线程也无法执行的状态

    ​ 等待锁 线程休眠 IO数据

  • 死亡态(消亡):线程正常将任务执行完成,或者碰到异常意外销毁

线程状态之间的关系:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C5rKRa4c-1646960593577)(C:\Users\12994\Desktop\死锁_线程池.assets\wpsD19B.tmp.jpg)]

获取线程的状态

以上所说的线程的状态,都是理论分析的状态,如果需要在代码中获取线程的状态,可以获取。

获取线程状态的方法:getState()

特点:该方法的返回值是Thread类中的内部类:State,该类型是一个枚举类,该类中定义了六个对象,来表示线程的六种状态对象。

罗列:

  • NEW:新建态
  • RUNNABLE:就绪态或者运行态
  • BLOCKED:阻塞态 IO数据导致的阻塞
  • WAITING:阻塞态 wait方法导致的阻塞
  • TIMED_WAITING:阻塞态 sleep方法导致的阻塞态
  • TERMINATED:死亡态
public static void main(String[] args) {
    Thread t = new Thread(){
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println("----");
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    //获取线程状态:新建态
    Thread.State s = t.getState();
    System.out.println(s);
    //获取线程状态:可能是就绪或者运行态、阻塞态、死亡态
    t.start();
    Thread.State s1 = t.getState();
    System.out.println(s1);
}

线程池

概述:用来存储线程的一个容器

使用线程池的原因:

  • 如果Java语言不支持线程池:

    • 想要使用新线程完成任务,自己创建一个线程对象,将任务对象提交给线程对象,启动线程,完成任务,当任务完成之后,该线程对象就会被销毁。如果程序种有很多任务,就需要花费很多的时间在线程的创建和销毁上,就降低了程序的运行效率。反复的对线程创建和销毁造成了资源的浪费。

    • 如果某条线程在执行任务的过程中,该线程被意外销毁了,那么就导致任务无法完成。

  • 如果Java语言提供了线程池:

    • 想要完成多个任务,不需要自己新创建线程对象,直接从线程池种获取线程来完成任务,解决创建线程对象的时间;当线程池种的线程完成任务之后,将该线程对象回收到线程池种,以后可以反复使用,避免了资源的浪费;如果线程池种的线程在完成任务的过程种被意外销毁,如果被销毁,线程池会继续分配线程完成该任务。

线程池的使用

步骤:

  • 获取线程池对象
  • 创建任务类对象
  • 将任务对象提交给线程池
  • 关闭线程池对象

获取线程池对象:

  • Executors:工具类获取线程池的工具类
  • newSingleThreadExecutor() :获取一个具有单个线程的线程池对象
  • newFixedThreadPool(int n) :获取一个有n条线程的线程池对象
  • newCachedThreadPool() :获取一个线程池对象,根据提交的任务分配线程

将任务提交给线程池对象:

submit(Runnable r);

  • 如果线程池种的线程少,任务多;存在的线程先并发完成任务,那一条线程先完成任务,就继续做等待的任务。

  • 如果线程池种线程多,任务少:首先随机分配线程去并发完成提交的任务,多余的线程等待任务的提交。

private static void test02() {
    //获取一个线程池对象:并指定线程池中的线程条数
    //-------当线程数量多余任务数的时候,有的不执行
    //-------当线程数量少于任务书的时候,先执行完的线程在执行没被执行的任务
    ExecutorService three = Executors.newFixedThreadPool(4);

    Runnable r1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("任务1-----"+Thread.currentThread().getName());
        }
    };

    Runnable r2 = new Runnable() {
        @Override
        public void run() {
            System.out.println("任务2-----"+Thread.currentThread().getName());
        }
    };
    Runnable r3 = new Runnable() {
        @Override
        public void run() {
            System.out.println("任务3-----"+Thread.currentThread().getName());
        }
    };

    //把任务提交线程
    three.submit(r1);
    three.submit(r2);
    three.submit(r3);
    //关闭线程池,关闭之后不能再继续提交任务
    three.shutdown();
}
  • 如果线程池中线程和任务一样多,线程之间并发完成任务。
//获取一个线程池对象:不指定线程数量,根据任务数量自动为其分配
        ExecutorService es = Executors.newCachedThreadPool();
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("任务1-----"+Thread.currentThread().getName());
            }
        };

        Runnable r2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("任务2-----"+Thread.currentThread().getName());
            }
        };
     

        es.submit(r1);
        es.submit(r2);
        //关闭线程池,关闭之后不能再继续提交任务
        es.shutdown();

关闭线程池的方法:

  • shutdown() :将已经提交的任务全部完成之后,再关闭线程池。关闭后,不能再提交
  • shutdownNow() :将正在运行的任务完成之后,关闭线程池。已经提交还没运行的任务,不再运行。
//把任务提交线程池,但是线程池中只有两个线程
three.submit(r1);
three.submit(r2);
three.submit(r3);
//关闭线程池,关闭之后不能再继续提交任务
three.shutdown();
//关闭后,r3任务也还没有运行
three.shutdownNow();

方法**:

  • shutdown() :将已经提交的任务全部完成之后,再关闭线程池。关闭后,不能再提交
  • shutdownNow() :将正在运行的任务完成之后,关闭线程池。已经提交还没运行的任务,不再运行。
//把任务提交线程池,但是线程池中只有两个线程
three.submit(r1);
three.submit(r2);
three.submit(r3);
//关闭线程池,关闭之后不能再继续提交任务
three.shutdown();
//关闭后,r3任务也还没有运行
three.shutdownNow();

记一次线程池使用导致的死锁 top统计的是当前统计窗口里的情况。一般情况下,只要不是宿主机上的所有容器负载都很大,超卖是没有影响的,即只要没有把物理机cpu打满,超卖就超卖,反正也用不完,但是只要某一时刻兄弟们要求的12个cpu都要用的时候,那就完了,物理机cpu使用率飙高,这个时候进程上下文切换更加频繁,雪上加霜,系统会更慢的。但还有一点人性没有泯灭,当时这么写的时候,其实有点膈应,但是一个闪念的想法让我就这么写了:任务里的操作其实会很快,因为有两层缓存,即走到了db,也一定走上索引,应该不会慢的,就这样吧,应该问题不大。 阅读详情

相关推荐

SAP接口错误查询日志

随着数字经济的迅速发展,企业数字化转型不在只追求“业财一体化”,而是在业务端也想要进行更为精细化的管理,所以很多企业在SAP ERP的基础上,集成更多垂直领域更精细的外围系统,比如销售CRM系统,采购SRM系统,生产MES系统等等,琳琅满目的产品,那对SAP实施来说,系统集成过程中,接口的一些报错查询能力必不可少,今天我们就介绍一下,SAP和CRM系统集成中接口常见的报错。

weixin_43657667的博客 2049

Java线程池实现多窗口卖票,同时使用CountDownLatch实现等待全部线程完成

线程池实现多窗口随机卖票个人原创,谢谢支持实现原理启动多线程卖票使用内置方法,等待多线程统一结束实现代码启动多线程类卖票代码实现 个人原创,谢谢支持 代码个人编写,实测有效,欢迎转载本文链接。https://blog.youkuaiyun.com/u014730287/article/details/103399779 实现原理 启动多线程卖票 使用 ExecutorService executorServi...

Zhaiyp的博客 793

Creo报错代码-9?手把手教你重新生成许可证文件(基于Creo 10.0)

本文详细解析Creo报错代码-9的成因及解决方案,重点介绍如何重新生成许可证文件以应对网络环境变化导致的验证失败。通过分步指南和高级技巧,帮助用户有效管理多网络环境下的Creo许可证问题,提升工作效率。

weixin_30839881的博客 562

【Java基础】多线程实例----三个窗口同时售卖100张车票【详解源码实现】

本一节作为前一节多线程的补充说明,旨在解决多线程问题中的线程安全问题的解决。 问题描述 假设售票厅有3个窗口可以售卖某次列车的最后100张车票,这三个窗口可以看做三个线程,100张车票可以看做三个线程共享的资源,仔细分析,这个问题中存在线程安全问题。 一.直接实现售票 1.继承Thread类,重run()方法 /** * 三个窗口买票:共售100张票 * 存在线程安全的问题 * @author wds * @date 2021-11-15-20:30 */ public class ThreadT

weixin_46081857的博客 1万+

开源 AHB不对称半桥反激电路设计(六)死区时间,谐振腔电流,谐振电感函数表达式

电流跌落可以使副边电流峰值和有效值降低,减小损耗,但如果开关管 S2 导通期间,谐振电流谐等于励磁电流,即副边电流A 点降至 0,会在原边变压器内形成环流,产生损耗,同时也不利于副边同步整流管驱动的正常工作,为了保证开关管 S2 导通期。在开关管 S1 和开关管 S2 均关断的死区时间内,谐振电流给原边开关管结电容和副边整流管结电容充放电,因此会引起开关 S1 关断瞬间电流跌落与开关 S2 关断瞬间电流震荡现象,受寄生参数影响原边谐振电流波形和副边电流波形如图。降到最低,变压器以最高效率向副边传递能量。

【Simon】的博客 1229

计算机网络之NAT的解释与实验配置

NAT 静态NAT 动态NAT easy_ip NAT服务器映射

爱学习的JackYang的博客 1918

创建三个窗口进行卖票 总票100张 使用实现Runnable接口的方法实现

例子:创建三个窗口进行卖票 总票100张 使用实现Runnable接口的方法 解决线程安全的问题: 当一个线程在操作ticket的时候,其他线程不能参与进来,直到线程A操作完ticket时候,其他线程才能开始操作,这种情况即使线程A出现了阻塞,也不能被改变 同步代码块:: synchronized(同步监视器){ 需要同步的代码 } 说明:操作共享数据的代码 就是同步代码 共享数据:多个线程共同操作的变量 如ticket 同步监视器:俗称:锁,任何一个类的对象都可以当做 要求:多个线程,必须共用同一

sunyingboaini的博客 869

【MATLAB】通过计算曲率和曲率变化率来实现对曲线波浪程度

这段代码将计算给定曲线的曲率,并与给定阈值进行比较以检测拐角。函数是MATLAB中一个常用的函数,可以用于计算曲线在每个点处的曲率。它基于一种被称为“local least squares fitting” 的方法,通过拟合每个点周围的一小段曲线来计算曲率。MATLAB中可以使用多种方法实现拐角检测,其中一种方法是基于曲率半径的算法。该算法通过计算曲线上每个点处的曲率半径,找到拐角和弯曲处。是一个可选参数,用于控制拟合曲线的平滑度,取值范围为0到1,越接近1表示曲线越平滑。表示曲线在每个点处的曲率,

Fanjufei的博客 1919

Java 多线程 解决线程安全问题的三种线程同步机制

先引入线程的生命周期 线程同步问题 再引入问题:模拟火车站售票程序,开启三个窗口售票。 package com.atguigu.java; /** * 使用Runnable接口的方式来实现 */ class window1 implements Runnable{ private int ticket=100; //注意此处没有加static,但三个线程共用同一个ticket @Override public void run() { while(tr

架构沉思录的博客 829

PowerDesigner 数据库建模使用详解

PowerDesigner 数据库建模使用详解

congge 7082

ORB-SLAM3算法2之EuRoc开源数据集运行ORB-SLAM3生成轨迹并用evo工具评估轨迹

ORB-SLAM3算法1 已成功编译安装ORB-SLAM3到本地,本篇目的是用EuRoc开源数据来运行ORB-SLAM3,并生成轨迹,最后用evo评估工具来评估ORB-SLAM3生成的轨迹和真值轨迹。

重点记录机器人和自动驾驶相关领域的技术,尤其是计算机视觉,视觉SLAM等,不仅有前言文献或必备算法的学习,也会有实际应用的点滴经验 3762

Java多线程示例:4个售票员卖1000张火车票

Java多线程示例:4个售票员卖1000张火车票 分类: JAVA 2011-11-17 01:14 112人阅读 评论(0) 收藏 举报 view plain //售票员  import java.util.Iterator;  import java.util.Map;      public class TicketSaler implements

6440

从零开始学习AI人工智能本体论:概念与实战

本文旨在为初学者提供一个全面而易于理解的人工智能本体论入门指南。我们将覆盖从基本概念到实际应用的全过程,帮助读者理解本体论在AI系统中的核心作用。核心概念与联系:介绍本体论的基本概念和原理核心算法与操作步骤:详细讲解本体构建和推理方法项目实战:通过实际案例展示本体论的应用实际应用场景:探讨本体论在不同领域的应用未来发展趋势:展望本体论在AI领域的前景本体论(Ontology): 在AI中,指对特定领域概念及其关系的明确形式化描述。

AI智能探索者的博客 868

线程池死锁

使用线程池的风险 死锁:虽然死锁可能发生在任何多线程程序中,但线程池引入了另一种死锁情况,其中所有正在执行的线程都在等待等待队列阻塞线程的结果,因为执行的线程不可用。 简言之:业务线程在占用了线程池内所有的资源后又向线程池提交了新的任务,并且要等这些任务完成后才释放资源,而这些新提交的任务根本就没机会被完成 线程泄漏:如果从池中删除线程以执行任务但在任务完成时未返回线程,则会发生线程泄漏。例...

weixin_30252155的博客 1824

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

java 线程池 死锁_JAVA中 死锁&线程池

死锁现象:DeadLock,当多线程访问互斥的网络资源时(共享资源,但是访问顺序相反),由于线程安全问题而加的多层同步,导致程序锁死现象,称为死锁。解决死锁的方法:尽量减少加的同步的次数。死锁代码示例:1 packageDemoList;23 public classDemo1 {45 public static voidmain(String[] args) {6 Ext...

weixin_30364109的博客 295

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

线程池的死锁事件

线程池的死锁问题

scwMason的博客 1402

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

死锁与线程池基础知识及案例

本文系统阐述了Java并发编程中的两大核心问题:死锁现象与线程池应用。在死锁部分,通过哲学家就餐案例揭示了死锁产生的四大必要条件(互斥、请求保持、非剥夺和循环等待),并给出典型代码示例:两个线程互相持有对方所需资源(KuaiZi.a和KuaiZi.b)导致永久阻塞。同步关键字synchronized的使用及Thread.sleep()模拟的延迟操作共同构成了死锁场景,文中同时提出了避免死锁的四种策略。

qq_52506743的博客 820

线程池终极指南 :如何避免线程池中的死锁问题

在Java的世界中,线程池是提升应用性能和资源利用率的关键技术。本文将深入探讨线程池的运行原理,应用场景,并结合源码分析,为你提供一份全面的线程池设置指南。通过理解线程池的运行原理,我们可以根据不同的应用场景和任务类型,设置合适的线程池大小。这只是线程池配置的一小部分,实际使用中,我们还需要根据应用的需要进行更多的配置。线程池死锁问题的解决方法通常涉及对线程池的使用进行调整,以及对应用程序的并发设计进行优化。如果线程池的任务队列已满,可以使用自定义的拒绝策略来处理新提交的任务,而不是让线程等待获取锁。

赵KK的博客 1500

mysql死锁占用线程池_Java 线程池死锁问题

一、线程池死锁1、资源互斥死锁这种死锁是最常见的经典死锁,假定存在 A、B 2个任务,A需要B的资源,B需要A的资源,双方都无法得到时便出现了死锁。//首先我们先定义两个final的对象锁.可以看做是共有的资源.final Object lockA = new Object();final Object lockB = new Object();//生产者Aclass ProductThread...

weixin_35797090的博客 288

JAVA中 死锁&线程池

JAVA中 死锁&线程池 死锁现象:DeadLock,当多线程访问互斥的网络资源时(共享资源,但是访问顺序相反),由于线程安全问题而加的多层同步,导致程序锁死现象,称为死锁。 解决死锁的方法:尽量减少加的同步的次数。 死锁代码示例: 1 package DemoList; 2 3 public class De...

qq_38830041的博客 309

【JAVASE】线程池和死锁

在多线程程序中,使用了多把锁,造成线程之间相互等待.程序不往下走了。

Robin的博客 227

线程池使用不当导致线程死锁

这时候已经提交到线程池的线程要等待队列中的任务运行,而队列中的任务又需要线程池中线程运行完成,释放后才能执行,最终导致线程池死锁。到线程池中,已经占满了它的线程池,后续我们又把每个tree的子节点提交到线程池中处理,此时会加入到线程池的等待队列中,而且必须要等到子节点处理完成后才返回(对应。在项目开发中,为了支持并发场景,减少资源开销,通常会使用公共线程池,即预先创建一个线程池,需要并发时都将任务提交该线程池中。然后我们思考处理逻辑,我们可以深度优先搜索遍历这个二叉树,然后返回叶子节点与根节点的最大值,

SpringBoy的博客 962

使用线程池实现死锁

使用线程池实现死锁 话不多说,开搞! import java.util.concurrent.*; /** *使用线程池实现死锁 *@author com.xiong * * */ public class DeadLockDemo { public static void main(String[] args) { //创建两个资源供线程共同操作 Object resource1 =new Object(); Object resourc

qq_37021992的博客 330

线程池+死锁

常见的线程池: (1)Executors.newCacheThreadPool():可缓存线程池,先查看池中有没有以前建立的线程,如果有,就直接使用。如果没有,就建一个新的线程加入池中。(可无限扩充,负载较轻的情况使用) (2) Executors.newFixedThreadPool(int n):创建一个可重用固定个数的线程池,以共享的无界队列方式来运行这些线程。(用于负载较重的情况使用,控制线程数量) (3)Executors.newScheduledThreadPool(int n):创建一个定长线

njh1147394013的博客 1498

全局共用一个线程池竟然发生死锁了

通过上面的 Demo 复现以及解决方案,在工作中优化建议如下。1、禁止使用Executors创建自定义线程池。使用创建线程池时,注意每个参数的含义,规避资源耗尽的风险。2、线程池使用有界队列,避免使用无界队列。3、对于父子任务的场景,可以使用线程池或者 MQ。使用有界队列之后,制定合理的拒绝策略,拒绝策略可以考虑 MQ 做重试。4、不同业务使用不同的线程池,禁止父子任务使用相同的线程池。

醉鱼的博客 1143

线程池执行父子任务,导致线程死锁

一次线程池的不当使用,导致了现场出现了线程死锁,接口一直不返回。而且由于这是一个公共的线程池,其他使用了次线程池的业务也一直阻塞,系统出现了OOM,不过是幸好是线程同事测试出来的,没有直接在生产坏境中出现这种事故,否则后果不堪设想。

ql_7256的博客 2108
上一篇: Mysql入门以及基础命令(数据库定义语言DDL)
下一篇: Mysql增删改查语句(DML、DQL)
皮卡丘不断更
博客等级 码龄5年 111粉丝 141原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮卡丘不断更

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值