后台开发知识点总结(三)Java并发

进程与线程的区别是什么?

进程就是一段程序的执行过程(狭义)。是一个具有特定功能的程序关于某个数据集合运行的一次运行活动,是操作系统分配资源的最基本单位(广义)。线程也称轻量级进程,是程序执行流的基本单元。在引入线程的操作系统中,一般都是把进程作为分配资源的基本单位,把线程作为独立运行和独立调度的基本单位。

主线程退出会导致整个进程退出么?

不一定。Java 中的 Thread 分为User Thread 和 Demon Thread(守护线程)。守护线程与用户线程的区别就在于,如果虚拟机中的线程都是守护线程的话,虚拟机(也就是进程。在java中,每个进程对应一个java虚拟机)将会退出。因此,在主线程退出的时候,如果虚拟机中还有其他的用户线程,虚拟机不会退出。否则,虚拟机中其他的线程都是守护线程,虚拟机将会退出。

守护线程和守护进程的区别是什么?

在一般情况下,当进程的控制终端被关闭的时候,进程会被强行关闭。守护进程是一种能够脱离于终端在后台运行的一种进程。它从被执行的时候开始运转,直到整个系统结束才退出。
守护线程跟一般意义上的线程(用户线程)的唯一区别在于,如果虚拟机中的线程都是守护线程的话,虚拟机(也就是进程)将会退出。
所以说,守护进程的“守护”跟守护线程的“守护”并不是相同的概念。

如何创建守护进程?

1.创建子进程fork(),父进程退出exit();
创建子进程后父进程退出,会导致子进程成为孤儿进程。孤儿进程将会被系统中的1号进程(init)所收养。这样。原来的子进程就变为了init进程的子进程。
2.在子进程中调用setsid();
setsid() 的作用是创建一个新的会话组,并担任新会话的组长。这样做可以使子进程脱离原来的终端、进程组和会话(一个进程组包含一个或多个进程,一个会话包含一个或多个进程组,通常把一个用户从登录到退出过程中,他运行的所有进程归于一个会话)。
3.改变根目录为当前目录chdir();
4.重设文件权限掩码umask();
使用umask()函数将当前进程的umask(当前进程所创建文件的初始权限掩码)置为0。
5.关闭文件描述符;
关闭不需要的文件描述符。

孤儿进程和僵尸进程的区别?

孤儿进程指的是父进程结束而子进程没有结束,而僵尸进程指的是子进程结束而父进程没有wait(或waitpid)它。

僵尸进程的危害与清除?

僵尸进程既不占用内存,也不占用cpu。但是它占用了一个进程号,系统所能够使用的进程号是有限的,因此僵尸进程大量地占用进程号将会导致无法生成新的进程。
清除僵尸进程的方法是:kill产生僵尸进程的父进程。这样僵尸进程就会变成孤儿进程,然后被内核回收。

怎么防止僵尸进程的出现?

1.通过父进程使用 wait() 或 waitpid() 等待子进程,这会导致父进程被挂起。(不过waitpid() 提供了一个无阻塞的wait(),只要把参数设置成 WNOHANG 就行了)。
2.用 signal() 函数为SIGCHLD 安装handler,子进程结束后,父进程会收到信号,可在 handler 中回收。
3.用 signal(SIGCHLD,SIG_IGN) 通知内核,由内核代为回收。
4.先创建子进程,再创建孙进程,创建结束之后杀死子进程,孙进程就会被 init 收养,由 init 回收。

僵尸进程会造成内存泄漏吗?

不会。内存泄漏指的是动态分配的内存空间,使用完之后未被释放。僵尸进程是不占用内存的(准确地说,是不占用java虚拟机的内存),就更谈不上内存泄漏了。

什么叫线程安全?

线程安全指的是在多线程环境下,程序执行的结果与各个线程的调度顺序无关。

使用线程池的好处?

一方面,使用线程池可以减小在创建和销毁线程时产生的时间开销和资源开销(因为在新任务到来时,不必再销毁和新建线程了)。另一方面,使用线程池可以管理线程,保证系统不会因为大量并发产生的资源不足而崩溃。

列举一下你所知道的线程池?

单线程线程池(NewSingleThreadExecutor)、固定数量的线程池(NewFixedThreadExecutor,达到最大数量后线程进入等待队列)、可缓存线程池(NewCachedThreadExecutor,自动回收60s未执行的线程)、大小无限制线程池(NewScheduleThreadExecutor)。

使用线程池的坏处是什么?

使用线程池可能带来额外的风险,比如:
线程池特有的死锁:所有线程都在阻塞等待某一任务的执行结果,而这一任务却因为没有线程而得不到执行。
资源不足:如果线程池太大可能引起不必要的资源浪费。
线程泄漏:有些线程被使用之后可能并不会返回线程池(比如等待某些资源或者用户输入),发生这种情况后线程池中可用线程数会减少。最后变得没有线程可以使用。