package org.kne.concurrent; import java.util.Queue; import java.util.concurrent.Executor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import org.jctools.queues.MpscArrayQueue; import org.kne.cloud.network.klalb.PerformanceStrategy; public class HighPerformanceExecutor2 implements Executor { private ThreadElement[] threads; public HighPerformanceExecutor2(int threadcount) { //this(threadcount,Executors.defaultThreadFactory()); this(threadcount,Thread.ofVirtual().factory()); } public HighPerformanceExecutor2(int threadcount,ThreadFactory th) { threads=new ThreadElement[threadcount]; for (int i = 0; i < threadcount; i++) { ThreadElement t= new ThreadElement(); th.newThread(t).start(); threads[i]=t; } } private static class ThreadElement implements Runnable{ private MpscArrayQueue queue=new MpscArrayQueue(2048); private AtomicInteger size=new AtomicInteger(); private volatile ThreadParker parker=new ThreadParker(); public Queue getQueue() { return queue; } public int size() { return queue.size(); } public long prev=System.nanoTime(); public boolean putTask(Runnable e) { boolean b=queue.offer(e); if(b) { // size.incrementAndGet(); long curr=System.nanoTime(); if(curr-prev>1000L||queue.size()>=8) { prev=curr; parker.unpark(); } } return b; } @Override public void run() { while(true) { Runnable r=queue.poll(); if(r!=null) { // size.decrementAndGet(); try { r.run(); }catch(Throwable e) { e.printStackTrace(); } ThreadYieldCheckpoint.yieldCheckpoint(1000000L); }else { parker.parkNanos(1000000L); } } } } @Override public void execute(Runnable command) { if(execute0((x)->{command.run();},1000, PerformanceStrategy.MULTI_FILL)) { return; } System.out.println("loss!"); //backup.execute(command); } private long vl=0; private boolean execute0(Consumer command, int limit, PerformanceStrategy strategy) { if(strategy.equals(PerformanceStrategy.MULTI_SCATTER)){ long ord=vl++; ThreadElement te= threads[(int) (ord%threads.length)]; boolean b=te.size()>limit; return te.putTask( ()->{command.accept(b);}); }else { for (int i = 0; i < threads.length; i++) { ThreadElement te = threads[i]; boolean b = te.size() > limit; if (!b) { if (te.putTask(() -> { command.accept(false); })) { return true; } } } for (int i = 0; i < threads.length; i++) { ThreadElement te = threads[i]; if (te.putTask(() -> { command.accept(true); })) { return true; } } return false; } } public void executeWithCongestionReport(Consumer command) { if(execute0(command,1000, PerformanceStrategy.MULTI_FILL)) { return; } System.out.println("loss!"); } public void executeWithCongestionReport(Consumer command, int limit, PerformanceStrategy strategy) { if(execute0(command,limit,strategy)) { return; } System.out.println("loss!"); } }