实现单机版任务调度的功能(分布式后续考虑,暂时先单进程)
1.首先管理员启动整个任务,并设置执行权限
2.工作节点收到消息后就会创建对应的线程,并开始执行任务(任务都是由一个管理员进行分配)
3.运行过程中管理员需要临时中断某个任务,需要设置一个互斥信号,此时对应的工作节点都需要被阻塞,注意不是完全销毁
自己总结一句话(例如有多个线程同时工作时候,设置一个变量,控制这些线程阻塞,或者活动)
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* 实现一个互斥实现,基于Cocurrent中的{@linkplain AbstractQueuedSynchronizer}实现了自己的sync <br/>
* 应用场景:系统初始化/授权控制,没权限时阻塞等待。有权限时所有线程都可以快速通过
*
* <pre>
* false : 代表需要被阻塞挂起,等待mutex变为true被唤醒
* true : 唤醒被阻塞在false状态下的thread
*
* BooleanMutex mutex = new BooleanMutex(true);
* try {
* mutex.get(); //当前状态为true, 不会被阻塞
* } catch (InterruptedException e) {
* // do something
* }
*
* mutex.set(false);
* try {
* mutex.get(); //当前状态为false, 会被阻塞直到另一个线程调用mutex.set(true);
* } catch (InterruptedException e) {
* // do something
* }
* </pre>
*
*/
public class BooleanMutex {
private Sync sync;
public BooleanMutex() {
sync = new Sync();
set(false);
}
public BooleanMutex(Boolean mutex) {
sync = new Sync();
set(mutex);
}
/**
* 阻塞等待Boolean为true
*
* @throws InterruptedException
*/
public void get() throws InterruptedException {
sync.innerGet();
}
/**
* 阻塞等待Boolean为true,允许设置超时时间
*
* @param timeout
* @param unit
* @throws InterruptedException
* @throws TimeoutException
*/
public void get(long timeout, TimeUnit unit) throws InterruptedException,TimeoutException {
sync.innerGet(unit.toNanos(timeout));
}
/**
* 重新设置对应的Boolean mutex
*
* @param mutex
*/
public void set(Boolean mutex) {
if (mutex) {
sync.innerSetTrue();
} else {
sync.innerSetFalse();
}
}
public boolean state() {
return sync.innerState();
}
/**
* Synchronization control for BooleanMutex. Uses AQS sync state to
* represent run status
*/
private final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -7828117401763700385L;
/** State value representing that TRUE */
private static final int TRUE = 1;
/** State value representing that FALSE */
private static final int FALSE = 2;
private boolean isTrue(int state) {
return (state & TRUE) != 0;
}
/**
* 实现AQS的接口,获取共享锁的判断
*/
@Override
protected int tryAcquireShared(int state) {
// 如果为true,直接允许获取锁对象
// 如果为false,进入阻塞队列,等待被唤醒
return isTrue(getState()) ? 1 : -1;
}
/**
* 实现AQS的接口,释放共享锁的判断
*/
@Override
protected boolean tryReleaseShared(int ignore) {
// 始终返回true,代表可以release
return true;
}
boolean innerState() {
return isTrue(getState());
}
void innerGet() throws InterruptedException {
super.acquireSharedInterruptibly(0);
}
void innerGet(long nanosTimeout) throws InterruptedException,TimeoutException {
if (!super.tryAcquireSharedNanos(0, nanosTimeout))
throw new TimeoutException();
}
void innerSetTrue() {
for (;;) {
int s = getState();
if (s == TRUE) {
return; // 直接退出
}
if (super.compareAndSetState(s, TRUE)) {// cas更新状态,避免并发更新true操作
releaseShared(0);// 释放一下锁对象,唤醒一下阻塞的Thread
}
}
}
void innerSetFalse() {
for (;;) {
int s = getState();
if (s == FALSE) {
return; // 直接退出
}
if (super.compareAndSetState(s, FALSE)) {// cas更新状态,避免并发更新false操作
setState(FALSE);
}
}
}
}
}
测试代码
@Test
public void test_init_true() {
BooleanMutex mutex = new BooleanMutex(true);
try {
mutex.get(); //不会被阻塞
} catch (InterruptedException e) {
want.fail();
}
}
@Test
public void test_init_false() {
final BooleanMutex mutex = new BooleanMutex(false);
try {
final CountDownLatch count = new CountDownLatch(1);
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(new Callable() {
public Object call() throws Exception {
Thread.sleep(1000);
mutex.set(true);
count.countDown();
return null;
}
});
mutex.get(); //会被阻塞,等异步线程释放锁对象
count.await();
executor.shutdown();
} catch (InterruptedException e) {
want.fail();
}
}
@Test
public void test_concurrent_true() {
try {
final BooleanMutex mutex = new BooleanMutex(true);
final CountDownLatch count = new CountDownLatch(10);
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
executor.submit(new Callable() {
public Object call() throws Exception {
mutex.get();
count.countDown();
return null;
}
});
}
count.await();
executor.shutdown();
} catch (InterruptedException e) {
want.fail();
}
}
@Test
public void test_concurrent_false() {
try {
final BooleanMutex mutex = new BooleanMutex(false);//初始为false
final CountDownLatch count = new CountDownLatch(10);
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
executor.submit(new Callable() {
public Object call() throws Exception {
mutex.get();//被阻塞
count.countDown();
return null;
}
});
}
Thread.sleep(1000);
mutex.set(true);
count.await();
executor.shutdown();
} catch (InterruptedException e) {
want.fail();
}
}