动态分配线程数目-保证系统负载
来源:互联网 发布:韩雪网络直播视频 编辑:程序博客网 时间:2024/05/17 18:18
package com.zte.sunquan.demo.executor;import com.google.common.util.concurrent.AtomicDouble;import com.google.common.util.concurrent.ThreadFactoryBuilder;import com.sun.management.OperatingSystemMXBean;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.lang.management.ManagementFactory;import java.lang.management.MemoryMXBean;import java.lang.management.MemoryUsage;import java.lang.management.ThreadMXBean;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.ThreadFactory;import java.util.concurrent.TimeUnit;/** * Created by sunquan on 2017/4/15. */public final class DynamicExecutorFactory { private static final Logger logger = LoggerFactory.getLogger(DynamicExecutorFactory.class); private static final int DEFAULT_THRESHOLD = 4; private static AtomicDouble atomicDouble = new AtomicDouble(0L); private static final boolean USELOAD = false; private static final String GROUP_NAME = "dynamic-factory"; private DynamicExecutorFactory() { } static { backgroundUpdate(); } public static ExecutorService getExecutorService(int expiredNum) { return getExecutorService(USELOAD, expiredNum); } public static ExecutorService getExecutorService(boolean useLoad, int expiredNum) { int threads; if (useLoad) { threads = getThreadNum(expiredNum); } else { threads = expiredNum <= DEFAULT_THRESHOLD ? expiredNum : DEFAULT_THRESHOLD; } logger.info("create threads={} and expiredNum={}", threads, expiredNum); return Executors.newFixedThreadPool(threads, GroupedThreadFactory.groupedThreadFactory(GROUP_NAME)); } private static int getThreadNum(int expiredNum) { if (expiredNum <= 2) return expiredNum; //注意第一次调用时,默认只给1个线程 int threadNum = (int) (expiredNum * atomicDouble.get()); return threadNum < 1 ? 1 : threadNum; } private static ThreadFactory getFactory(String groupName, String name, boolean daemon) { ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder(); threadFactoryBuilder.setNameFormat(name) .setThreadFactory(GroupedThreadFactory.groupedThreadFactory(groupName)); threadFactoryBuilder.setDaemon(daemon); return threadFactoryBuilder.build(); } private static void backgroundUpdate() { ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(getFactory("dynamic-load-schedule", "s1", true)); executorService.scheduleWithFixedDelay(new CalSysLoadTask(), 10, 3, TimeUnit.SECONDS); } private static class CalSysLoadTask implements Runnable { final OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class); final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); final ThreadMXBean thread = ManagementFactory.getThreadMXBean(); @Override public void run() { double systemCpuLoad = 0; double processCpuLoad = 0; double usage = 0; double threadRadio = 0; double swapSpaceRadio = 0; try { systemCpuLoad = operatingSystemMXBean.getSystemCpuLoad(); processCpuLoad = operatingSystemMXBean.getProcessCpuLoad(); MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage(); usage = (double) memoryUsage.getUsed() / (double) memoryUsage.getCommitted(); double threadCount = (double) thread.getThreadCount(); double peakThreadCount = (double) thread.getPeakThreadCount(); threadRadio = 0L; if (threadCount < peakThreadCount) { threadRadio = 1 - threadCount / peakThreadCount; } else { threadRadio = 1 - peakThreadCount / threadCount; } long freeSwapSpaceSize = operatingSystemMXBean.getFreeSwapSpaceSize(); long totalSwapSpaceSize = operatingSystemMXBean.getTotalSwapSpaceSize(); swapSpaceRadio = (double) freeSwapSpaceSize / (double) totalSwapSpaceSize; atomicDouble.set((1 - systemCpuLoad) * 0.2 + (1 - processCpuLoad) * 0.2 + (1 - usage) * 0.1 + threadRadio * 0.3 + swapSpaceRadio * 0.2); } catch (Exception e) { logger.error("backgroundUpdate error =", e); } finally { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("systemCpuLoad:").append(systemCpuLoad) .append("processCpuLoad:").append(processCpuLoad) .append("usage:").append(usage) .append("threadRadio:").append(threadRadio) .append("swapSpaceRadio:").append(swapSpaceRadio) .append("load:").append(atomicDouble.get()); logger.info(stringBuilder.toString()); } } }}
package com.zte.sunquan.demo.executor;import com.google.common.collect.Maps;import java.util.Map;import java.util.concurrent.ThreadFactory;/** * Created by sunquan on 2017/4/15. */public class GroupedThreadFactory implements ThreadFactory { private final ThreadGroup group; private static final Map<String, GroupedThreadFactory> FACTORIES = Maps.newConcurrentMap(); public GroupedThreadFactory(ThreadGroup group) { this.group = group; } @Override public Thread newThread(Runnable r) { return new Thread(group, r); } public static GroupedThreadFactory groupedThreadFactory(String groupName) { //oscp/a/b/c GroupedThreadFactory groupedThreadFactory = FACTORIES.get(groupName); if (groupedThreadFactory != null) { return groupedThreadFactory; } int i = groupName.lastIndexOf("/"); if (i > 0) { String parentGroupName = groupName.substring(0, i); ThreadGroup parentGroup = groupedThreadFactory(parentGroupName).getGroup(); groupedThreadFactory = new GroupedThreadFactory(new ThreadGroup(parentGroup, groupName)); } else { groupedThreadFactory = new GroupedThreadFactory(new ThreadGroup(groupName)); } FACTORIES.putIfAbsent(groupName,groupedThreadFactory); return groupedThreadFactory; } public ThreadGroup getGroup() { return group; }}
测试:
package com.zte.sunquan.demo.executor;import com.google.common.util.concurrent.ThreadFactoryBuilder;import org.junit.Test;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;/** * Created by sunquan on 2017/4/15. */public class ExecutorTest { public ThreadFactory getFactory(String groupName, String name) { ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder(); threadFactoryBuilder.setNameFormat(name) .setThreadFactory(GroupedThreadFactory.groupedThreadFactory(groupName)); return threadFactoryBuilder.build(); } @Test public void test() throws InterruptedException { //对每一个事件都要定义其所在的事件组,事件名,并保持相关继承关系 CountDownLatch countDownLatch = new CountDownLatch(1); ExecutorService executorService = Executors.newFixedThreadPool(2, getFactory("sqGroup/a/b", "sqThread%d")); executorService.execute(() -> { System.out.println("hello,world"); System.out.println("ThreadParentGroup:" + Thread.currentThread().getThreadGroup().getParent().getName()); System.out.println("ThreadGroup:" + Thread.currentThread().getThreadGroup().getName()); System.out.println("ThreadName:" + Thread.currentThread().getName()); countDownLatch.countDown(); }); countDownLatch.await(); System.out.println(Thread.currentThread().getThreadGroup().getName()); } @Test public void dTest() throws InterruptedException { ExecutorService executorService = DynamicExecutorFactory .getExecutorService(true, 50);//只有1个线程 Thread.sleep(15000); DynamicExecutorFactory.getExecutorService(true, 50);//压力计算得26个线程// Thread.currentThread().join(); }}