134 lines
3.1 KiB
Java
134 lines
3.1 KiB
Java
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<Runnable> queue=new MpscArrayQueue<Runnable>(2048);
|
|
private AtomicInteger size=new AtomicInteger();
|
|
|
|
private volatile ThreadParker parker=new ThreadParker();
|
|
public Queue<Runnable> 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<Boolean> 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<Boolean> command) {
|
|
if(execute0(command,1000, PerformanceStrategy.MULTI_FILL)) {
|
|
return;
|
|
}
|
|
System.out.println("loss!");
|
|
}
|
|
public void executeWithCongestionReport(Consumer<Boolean> command, int limit, PerformanceStrategy strategy) {
|
|
if(execute0(command,limit,strategy)) {
|
|
return;
|
|
}
|
|
System.out.println("loss!");
|
|
|
|
|
|
}
|
|
}
|