多线程并发会造成程序周期性崩溃吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程并发会造成程序周期性崩溃吗?相关的知识,希望对你有一定的参考价值。

比如我开了多线程的任务,然后程序差不多一天崩溃一次,这种情况有可能吗?

只有线程处理出错才会造成奔溃,简单举个例子,线程刷新控件,你用整个父容器去invork,invork有Begin和end,前提条件还需要你已经创建了句柄,当窗体启动后,系统还会在后台启动窗体重绘,这时候线程开启了子线程,如果他快过主线程启动,那么它就会报从不创建句柄的控件更新ui错误,你不抛出强行执行,就会造成系统奔溃。所以控件少用invork,传值用传值对象去Post,界面使用传值方法,回调你要做接口。另一个典型的错误来自于,你创建了N个子线程,你不确定它到底有没有全部完成,主线程干掉了,对不起,子线程还没完呢?你都不处理一下,也不abort也不kill,程序就会溢出奔溃......周期性奔溃你用计时器,子线程没有闭环,直接new一个对象然后直接start,就没有处理abort机制,它能不奔溃吗?有些ui刷新动作,你不注意句柄和控件和容器的关系,它绝对也是要奔溃的。 参考技术A 多线程并发处理,会加大内存的消耗。因为线程数过多的话,每个线程都在独立处理数据,对内存的消耗是之前很多倍。

Java并发编程:线程的生命周期是个怎样的过程?

前言

在日常开发过程中,如果我们需要执行一些比较耗时的程序的话,一般来说都是开启一个新线程,把耗时的代码放在线程里,然后开启线程执行。但线程是会耗费系统资源的,如果有多个线程同时运行,互相之间抢占系统资源,那无疑会对系统造成极大的压力。所以,怎么操作线程,保证不影响整个应用功能是很重要的,而这就需要我们了解线程的生命周期了。

线程的生命周期

线程的生命周期有6种状态,分别是NEW(新建)、RUNNABLE(可运行)、BLOCKED(被阻塞)、 WAITING(等待)、TIMED_WAITING(计时等待)、TERMINATED(被终止),在 Thread 源码的 State 枚举中都有定义:

public static enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;

    private State() {
    }
}

1、NEW 状态表示刚刚创建的线程,此时的线程还没运行,也就是还没执行start() 方法,创建线程的方式也比较简单,可以参考《Java并发编程:Java创建线程的三种方式》

2、当线程执行时,处于 RUNNABLE 状态,表示线程所需的资源已经准备好了。

3、如果线程在执行的过程中遇到被阻塞的情况,例如线程中的程序中有synchronized 同步代码块,线程就会暂停执行,进入阻塞状态,直至获取请求的锁,这时线程就处于 BLOCKED 状态。

实例代码如下:

public class ThreadDemo {
	
    public static Object testObject = new Object();

    public static class MyThread extends Thread {

        public MyThread(String name) {
            super.setName(name);
        }

        @Override
        public void run() {
			//每次跑run方法都需要获取testObject对象
            synchronized (testObject) {
                System.out.println("thread name:" + this.getName());

                //..............耗时操作..............
            }
        }

    }

    public static void main(String[] args) {
        for (int i = 1; i <= 100; i++) {
            new MyThread("线程"+i).start();
        }
    }
}

在上面的代码中,线程的run方法在执行耗时的程序之前都需要先获取testobject对象的锁,因为对象锁是公共对象,所以,多个线程同时运行时,同一时刻只能有一个线程获取锁,假设某个时刻是 A线程 获取了锁,其他线程就会处于等待锁释放的阻塞状态,直到获取锁才能继续执行程序,这就是线程的BLOCKED 状态。

4、WAITING 表示等待的状态,处于 WAITING 状态的线程会进入一个无时间限制的等待,一旦等到了期望的事件,线程就会再次执行,进入RUNNABLE 状态。最典型的场景就是 等待(wait)通知(notify)

等待状态对应的方法是wait(),而通知是notify(),这两个方法并不属于Thread类,而是属于Object类,所以所有对象都可以使用这两个方法。当一个对象实例 obj 调用 wait() 方法后,当前线程就会在这个对象上等待,直到其他线程调用 obj.notify() 为止。这时的对象实例 obj 就相当于多个线程之间的通信工具。实例代码如下:

public class ThreadDemo {

    public static Object testObject = new Object();

    public static class MyThread1 extends Thread {
        @Override
        public void run() {
            synchronized (testObject) {
                System.out.println("MyThread1 wait :" + System.currentTimeMillis());
                try {
                    //调用wait方法进入等待状态
                    testObject.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static class MyThread2 extends Thread {
        @Override
        public void run() {

            synchronized (testObject) {
                System.out.println("MyThread2 start notify :" + System.currentTimeMillis());
                //..............耗时操作..............

                //发出通知,唤醒等待的线程
                testObject.notify();
            }
        }
    }

    public static void main(String[] args) {
        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();
        t1.start();
        t2.start();
    }
}

5、TIMED_WAITINGWAITING 一样,都表示等待状态,但TIMED_WAITING 会进行一个 有时限的等待。操作线程状态有几个方法是带有超时参数的,调用方法的线程进入计时等待状态。这一状态将一直保持到超时期满或者接收到适当的通知,最常见的应用就是调用 Thread.sleep() 方法。

实例代码如下:

public static class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread start :" + System.currentTimeMillis());
        try {
        //休眠两秒钟
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyThread end :" + System.currentTimeMillis());
    }
}
public static void main(String[] args) {
        MyThread t = new MyThread1();
        t.start();
 }

启动线程后,程序运行到 Thread.sleep() 方法会处于休眠状态,时间根据参数来决定,单位是毫秒,所以执行main方法后,后一条输出内容会隔两秒钟出现。

MyThread start :1544704974271
MyThread end :1544704976272

6、当线程执行完毕后,进入 TERMINATED 状态,表示结束,一般线程被终止有两种原因:

  • run方法正常运行后就自然消亡。

  • 因为一个没有捕获的异常终止了run方法而导致意外死亡。

好了,线程的生命周期就总结完了,用一张图表示大概是这样:

以上是关于多线程并发会造成程序周期性崩溃吗?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA笔记(19)--- 线程概述;如何实现多线程并发;线程生命周期;Thread常用方法;终止线程的三种方式;线程安全问题;synchronized 实现同步线程模型;

Java多线程并发02——线程的生命周期与常用方法

java并发系列-----多线程简介创建以及生命周期

Java多线程与并发——线程生命周期和线程池

线程同步和并发

并发编程多线程基础