如何优先考虑在信号量中等待的线程?
how to give priority to the threads waiting in a semaphore?
我已经使用信号量来限制访问函数的线程数。我希望下一个被唤醒的线程应该由我将给予的一些优先级来选择,而不是默认情况下信号量唤醒它们的方式?我们怎样才能做到这一点?
这是实现:
class MyMathUtil2 implements Runnable {
double a;
double b;
String name = "demo";
Thread t;
//static int currentCount = 0;
static int MAX_COUNT = 2;
private final Semaphore available = new Semaphore(MAX_COUNT, true);
MyMathUtil2(double v1, double v2) {
a = v1;
b = v2;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start();
}
public void InternalPow(double a, double b) throws InterruptedException {
available.acquire();
try {
System.out.println("Power of " + a + " and " + b + " : " + Math.pow(a, b));
} finally {
available.release();
}
}
public void run() {
try {
InternalPow(a, b);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class TestMyMathUtil2 {
public static void main(String args[]) {
new MyMathUtil2(10.2, 8);
new MyMathUtil2(11, 56);
new MyMathUtil2(10.2, 9);
new MyMathUtil2(2, 3);
new MyMathUtil2(4, 5);
}
}
嗯,一个Semaphore
不支持优先级。
我建议使用ThreadPoolExecutor
with 2
fixed threads and a PriorityBlockingQueue
来解决这个问题。
具有2
个固定线程的ThreadPoolExecutor
可以确保在任何时刻最多有2
个任务运行。其他任务将放在这个 PriorityBlockingQueue
中,线程池将根据自定义 Comparator
.
从队列中检索任务
这是一个例子。本例中的每个 Runnable
都应该打印一个数字。它以相反的顺序提交 Runnable
s:1000, 999, ..., 1。
但是 Runnable
将按自然顺序执行:1、2、....、1000 使用优先级队列。
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
class ComparableRunnable implements Runnable {
public int index;
ComparableRunnable(int index) {
this.index = index;
}
public void run() {
System.out.println(Thread.currentThread().getName() + "-index : " + index);
try {
// sleep current thread, so the other thread can print
// this is not mandatory, without this, the result might not follow strict natural order
// for example, thread1 print 1,
// thread2 take 2 but did not print it immediatly,
// thread1 print 3,
// thread2 print 2
// the result will be 1, 3, 2,
Thread.sleep(10);
} catch (Exception e) {
}
}
public static void main(String[] args) {
int corePoolSize = 2; // fixed thread number
long ignore = 0L;
// comparator
Comparator<Runnable> comparator = new Comparator<Runnable>() {
@Override
public int compare(Runnable o1, Runnable o2) {
int index1 = ((ComparableRunnable)o1).index;
int index2 = ((ComparableRunnable)o2).index;
// you should implement this method based on your own order
return Integer.compare(index1, index2);
}
};
// use the comparator create a priority queue
PriorityBlockingQueue<Runnable> queue = new PriorityBlockingQueue<>(10, comparator);
ThreadPoolExecutor executor =
new ThreadPoolExecutor(corePoolSize, corePoolSize, ignore, TimeUnit.SECONDS, queue);
// Warm the thread pool up
// this is not mandatory, without this, it will print 1000, 999, 1, 2, ...., 998
// because the first two Runnbale will be executed once they are submitted
for (int i = 0; i < corePoolSize; i++) {
executor.execute(() -> {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
});
}
// submit in 1000, 999, ..., 1 order
// print in 1, 2, 3, ..., 1000 order
for (int i = 1000; i > 0; i--) {
executor.execute(new ComparableRunnable(i));
}
}
}
结果:
pool-1-thread-1-index : 1
pool-1-thread-2-index : 2
pool-1-thread-1-index : 3
pool-1-thread-2-index : 4
pool-1-thread-2-index : 5
...
pool-1-thread-2-index : 996
pool-1-thread-2-index : 997
pool-1-thread-1-index : 998
pool-1-thread-2-index : 999
pool-1-thread-1-index : 1000
我已经使用信号量来限制访问函数的线程数。我希望下一个被唤醒的线程应该由我将给予的一些优先级来选择,而不是默认情况下信号量唤醒它们的方式?我们怎样才能做到这一点?
这是实现:
class MyMathUtil2 implements Runnable {
double a;
double b;
String name = "demo";
Thread t;
//static int currentCount = 0;
static int MAX_COUNT = 2;
private final Semaphore available = new Semaphore(MAX_COUNT, true);
MyMathUtil2(double v1, double v2) {
a = v1;
b = v2;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start();
}
public void InternalPow(double a, double b) throws InterruptedException {
available.acquire();
try {
System.out.println("Power of " + a + " and " + b + " : " + Math.pow(a, b));
} finally {
available.release();
}
}
public void run() {
try {
InternalPow(a, b);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class TestMyMathUtil2 {
public static void main(String args[]) {
new MyMathUtil2(10.2, 8);
new MyMathUtil2(11, 56);
new MyMathUtil2(10.2, 9);
new MyMathUtil2(2, 3);
new MyMathUtil2(4, 5);
}
}
嗯,一个Semaphore
不支持优先级。
我建议使用ThreadPoolExecutor
with 2
fixed threads and a PriorityBlockingQueue
来解决这个问题。
具有2
个固定线程的ThreadPoolExecutor
可以确保在任何时刻最多有2
个任务运行。其他任务将放在这个 PriorityBlockingQueue
中,线程池将根据自定义 Comparator
.
这是一个例子。本例中的每个 Runnable
都应该打印一个数字。它以相反的顺序提交 Runnable
s:1000, 999, ..., 1。
但是 Runnable
将按自然顺序执行:1、2、....、1000 使用优先级队列。
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
class ComparableRunnable implements Runnable {
public int index;
ComparableRunnable(int index) {
this.index = index;
}
public void run() {
System.out.println(Thread.currentThread().getName() + "-index : " + index);
try {
// sleep current thread, so the other thread can print
// this is not mandatory, without this, the result might not follow strict natural order
// for example, thread1 print 1,
// thread2 take 2 but did not print it immediatly,
// thread1 print 3,
// thread2 print 2
// the result will be 1, 3, 2,
Thread.sleep(10);
} catch (Exception e) {
}
}
public static void main(String[] args) {
int corePoolSize = 2; // fixed thread number
long ignore = 0L;
// comparator
Comparator<Runnable> comparator = new Comparator<Runnable>() {
@Override
public int compare(Runnable o1, Runnable o2) {
int index1 = ((ComparableRunnable)o1).index;
int index2 = ((ComparableRunnable)o2).index;
// you should implement this method based on your own order
return Integer.compare(index1, index2);
}
};
// use the comparator create a priority queue
PriorityBlockingQueue<Runnable> queue = new PriorityBlockingQueue<>(10, comparator);
ThreadPoolExecutor executor =
new ThreadPoolExecutor(corePoolSize, corePoolSize, ignore, TimeUnit.SECONDS, queue);
// Warm the thread pool up
// this is not mandatory, without this, it will print 1000, 999, 1, 2, ...., 998
// because the first two Runnbale will be executed once they are submitted
for (int i = 0; i < corePoolSize; i++) {
executor.execute(() -> {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
});
}
// submit in 1000, 999, ..., 1 order
// print in 1, 2, 3, ..., 1000 order
for (int i = 1000; i > 0; i--) {
executor.execute(new ComparableRunnable(i));
}
}
}
结果:
pool-1-thread-1-index : 1
pool-1-thread-2-index : 2
pool-1-thread-1-index : 3
pool-1-thread-2-index : 4
pool-1-thread-2-index : 5
...
pool-1-thread-2-index : 996
pool-1-thread-2-index : 997
pool-1-thread-1-index : 998
pool-1-thread-2-index : 999
pool-1-thread-1-index : 1000