APEU2对于 僵尸进程(zombie process) 的定义:
In UNIX System terminology, a process that has terminated, but whose parent has not yet waited for it, is called a zombie
父线程在子线程结束时,没有进入 wait 方法获取子线程的终止状态,子线程终止后就是僵尸进程。
使用 ps aux | grep Z 查看 STAT 为 Z 的进程
kill父进程
ps -e -o ppid,stat | grep Z | cut -d" " -f2 | xargs kill -9
在服务器压力特别大,心跳经常丢失从而造成服务超时。经过分析发现网络没有问题,心跳网络包都发过来了而且也正常进入了dispatch队列,但是由于dispatch在处理别的request的时候耗时过长,而且要命的是它还hold着一把全局的锁,导致队列里面的其他queue也无法正常被dispatch。所以我们想到可以利用设置CPU亲和性来保证 核心进程/线程 得到足够的时间片,从而不让服务超时。
说到亲和性,如果我们不隔离CPU,那么就只能减少CPU切换,提高cpu cache的命中率,从而减少内存访问损耗,提高程序的速度。但是这样做只能保证自己不被调度到的别的CPU,却不能阻止其他线程不来我这个CPU。这样就成了“ 我的是公共的,别人的我不能用! ”,岂不是我得到的时间片更少了?所以为了防止这样的窘境,我们还得先“ 隔核 ”再“ 绑核 ”。
我们可以用如下命令来查看自己的服务器有多少个核心:
隔核方法: 修改grub
环境: CentOS7
具体步骤: (隔离4,5核心)
更改一个进程的CPU affinity mask,可以设置一个进程在某个CPU核心上执行,也可以设置该进程在除了某CPU 核心之外的其他CPU核心上执行。如果第一个参数pid为0,则设置当前进程的mask。
其实这个mask是一个针对线程组内的线程属性,可以被独立调节。所以我们可以用gettid()的参数作为第一个参数,同样如果第一个参数为0,则设置当前线程。如果传的getpid的返回值,则设置该线程组的主线程mask属性。
更改一个线程的CPU affinity mask, 同样也是可以设置一个线程在某个CPU核心上执行,也可以设置该线程在除了某CPU 核心之外的其他CPU核心上执行。这两个接口在底层也是调用sched_setaffinity/sched_getaffinity。当第一个参数为0时,就是设置当前thread的mask。
上面我们介绍了两种设置CPU affinity mask的接口,但是无论是哪一种接口有个共同的特性:创建出来的子线程默认会继承父亲线程的CPU affinity mask。在复杂的系统中有时并不希望这个属性的出现,因为可能会导致某个隔离出来的cpu上还是运行了很多的thread。所以我就想了一个解决方案来解决这个问题。
<1> >
你这种想法没得问题但是不是最好的, 我推荐你使用事件来推送
思路如下:
子线程监听客户端发送的消息
当子线程收到消息之后, 建立一份数据的拷贝 然后清楚buffer 向父线程通过事件推送此数据
父线程订阅该事件,拿到推送过来的数据直接处理
这样做的好处比你那个来讲,
不需要考虑线程同步的问题
使用的推模式 而不是拉模式(轮询模式)
如果不会写的话,可以留言,我可以帮你写一个。
你的问题不是很清楚,你是想在父线程里面创建子线程?然后父线程能关闭子线程?
Thread thread_1 = new Thread(new ThreadStart(thread_1));
thread_1 IsBackground = true;
thread_1 Start();
这不就创建了个线程么。然后同样方法在主线程函数里面在创建个线程
private void thread_1()
{
Thread thread_2 = new Thread(new ThreadStart(thread_2));
thread_2 IsBackground = true;
thread_2 Start();
}
如果父线程想控制子线程。最简单方式创建全局变量。public static bool flag;
父线程 *** 作这个变量,子线程判断这个变量,一旦发现变了,子线程就退出呗。大概就这思想吧。可能又更好的,我没用过。就这全局标志挺好使的
这里给你提供基本思路: 主线程CreateThread创建新线程之后,将返回的线程句柄,用于WaitForSingleObject。 效果是主线程创建完新线程后,等待新线程执行完返回,才继续执行,具体API用法请自行百度。
1一个线程的集合,也可包含其他线程组
2线程组构成一棵树,除了初始化线程组外,每一个线程组都有一个父线程组
3允许线程访问有关自己的线程组的信息,但不能访问其父线程组或其他线程组的信息
4ThreadGroup类只能获得处于运行状态的线程
常用方法:
activeCount() 返回线程组中活动线程的估计数
activeGroupCount() 返回线程组中活动线程组的估计数
enumerate(Thread[] list,boolean recurse) 把此线程组中所有活动线程复制到指定数组中
enumerate(ThreadGroup[] list,boolean recurse) 把此线程组中所有活动子组的引用复制到指定的数组中
enumerate(Thread[] list) 把此线程组中所有活动线程复制到指定数组中
enumerate(ThreadGroup[] list) 把此线程组中所有活动子组的引用复制到指定的数组中
getName() 返回此线程组的名称
getParent() 返回此线程组的父线程组
代码例子:
package comxhjthread;
import javautilArrayList;
import javautilList;
/
查看JVM中的线程 获取线程名和子线程组
@author XIEHEJUN
/
public class CheckThreadJVM {
/
获取根线程组
@return
/
public static ThreadGroup getRootThreadGroup() {
ThreadGroup rootGroup = ThreadcurrentThread()getThreadGroup();
while (true) {
if (rootGroupgetParent() != null) {
rootGroup = rootGroupgetParent();
} else {
break;
}
}
return rootGroup;
}
/
获取线程组中的线程名
@param group
@return
/
public static List<String> getThreadsName(ThreadGroup group) {
List<String> threadList = new ArrayList<String>();
Thread[] threads = new Thread[groupactiveCount()];
int count = groupenumerate(threads, false);
for (int i = 0; i < count; i++) {
threadListadd(groupgetName() + "线程组: " + threads[i]getName());
}
return threadList;
}
/
获取根数组下的子数组
@param group
@return
/
public static List<String> getThreadGroup(ThreadGroup group) {
List<String> threadList = getThreadsName(group);
ThreadGroup[] threads = new ThreadGroup[groupactiveGroupCount()];
int count = groupenumerate(threads, false);
for (int i = 0; i < count; i++) {
threadListaddAll(getThreadsName(threads[i]));
}
return threadList;
}
public static void main(String[] args) {
for (String string : getThreadGroup(getRootThreadGroup())) {
Systemoutprintln(string);
}
}
}
以上就是关于Ubuntu 僵尸进程查看与清理全部的内容,包括:Ubuntu 僵尸进程查看与清理、Linux CPU Affinity、C#,如何实现子线程一直监听数据、父线程定时从全局变量取数据等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)