in java.util.concurrent.FutureTask#run
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
} }
what's mean of finally block comment ?
run() method cannot be concurrent called, because of the CAS .
why must wait the INTERRUPTING -> INTERRUPTED state transform finished ?
thank you !
Related
In my opinion, run method in Thread is invoked by jvm, is there a concurrency problem? when I read FutureTask's source code, I found it use CAS to set current thread. Why can't use:
runner = Thread.currentThread()
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
}
Also, why don't use if (state != NEW && !UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread())) so that run method can only be execute once,then set(result) can replace to
protected void set(V v) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
not
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
Is there necessary to use CAS?
when I use Future<Integer> futureTask1 = executor.submit(callable),submit method will RunnableFuture<T> ftask = newTaskFor(task). If I use
FutureTask futureTask = new FutureTask(new Callable() {
#Override
public Object call() throws Exception {
return null;
}
})
new Thread(futureTask);
new Thread(futureTask);
this is useless. So in diffrent threads there are diffrent RunnableFuture Object,therefore, there is no need for guarantee concurrent calls to run(), Could someone tell me what I miss,thanks
Developers who are new to the workplace are trying hard to learn multithreading knowledge, thank you for your answers
broker start up is not exit,where the code shows the block?
i find some shedule,but not find anywhere await.
in this code,i just fond some server,but execute over this,why main thread not exit?
i enter server to find some detail,and just find some shedules,not find anywhere do wait() to blocking the main therad?
public void start() throws Exception {
if (this.messageStore != null) {
this.messageStore.start();
}
if (this.remotingServer != null) {
this.remotingServer.start();
}
if (this.fastRemotingServer != null) {
this.fastRemotingServer.start();
}
if (this.fileWatchService != null) {
this.fileWatchService.start();
}
if (this.brokerOuterAPI != null) {
this.brokerOuterAPI.start();
}
if (this.pullRequestHoldService != null) {
this.pullRequestHoldService.start();
}
if (this.clientHousekeepingService != null) {
this.clientHousekeepingService.start();
}
if (this.filterServerManager != null) {
this.filterServerManager.start();
}
if (!messageStoreConfig.isEnableDLegerCommitLog()) {
startProcessorByHa(messageStoreConfig.getBrokerRole());
handleSlaveSynchronize(messageStoreConfig.getBrokerRole());
this.registerBrokerAll(true, false, true);
}
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
BrokerController.this.registerBrokerAll(true, false, brokerConfig.isForceRegister());
} catch (Throwable e) {
log.error("registerBrokerAll Exception", e);
}
}
}, 1000 * 10, Math.max(10000, Math.min(brokerConfig.getRegisterNameServerPeriod(), 60000)), TimeUnit.MILLISECONDS);
if (this.brokerStatsManager != null) {
this.brokerStatsManager.start();
}
if (this.brokerFastFailure != null) {
this.brokerFastFailure.start();
}
}
Maybe you need What is a daemon thread in Java?.
Because each scheduler has some thread are running, and they are NON-DAEMON threads, so before these threads are finished, the jvm will not exit.
I am writing a job queue using BlockingQueue and ExecutorService. It basically waiting new data in the queue, if there are any data put into the queue, executorService will fetch data from queue. But the problem is that i am using a loop that loops to wait the queue to have data and thus the cpu usage is super high.
I am new to use this api. Not sure how to improve this.
ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
BlockingQueue<T> mBlockingQueue = new ArrayBlockingQueue();
public void handleRequests() {
Future<T> future = mExecutorService.submit(new WorkerHandler(mBlockingQueue, mQueueState));
try {
value = future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
if (mListener != null && returnedValue != null) {
mListener.onNewItemDequeued(value);
}
}
}
private static class WorkerHandler<T> implements Callable<T> {
private final BlockingQueue<T> mBlockingQueue;
private PollingQueueState mQueueState;
PollingRequestHandler(BlockingQueue<T> blockingQueue, PollingQueueState state) {
mBlockingQueue = blockingQueue;
mQueueState = state;
}
#Override
public T call() throws Exception {
T value = null;
while (true) { // problem is here, this loop takes full cpu usage if queue is empty
if (mBlockingQueue.isEmpty()) {
mQueueState = PollingQueueState.WAITING;
} else {
mQueueState = PollingQueueState.FETCHING;
}
if (mQueueState == PollingQueueState.FETCHING) {
try {
value = mBlockingQueue.take();
break;
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage(), e);
break;
}
}
}
Any suggestions on how to improve this would be much appreciated!
You don't need to test for the queue to be empty, you just take(), so the thread blocks until data is available.
When an element is put on the queue the thread awakens an value is set.
If you don't need to cancel the task you just need:
#Override
public T call() throws Exception {
T value = mBlockingQueue.take();
return value;
}
If you want to be able to cancel the task :
#Override
public T call() throws Exception {
T value = null;
while (value==null) {
try {
value = mBlockingQueue.poll(50L,TimeUnit.MILLISECONDS);
break;
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage(), e);
break;
}
}
return value;
}
if (mBlockingQueue.isEmpty()) {
mQueueState = PollingQueueState.WAITING;
} else {
mQueueState = PollingQueueState.FETCHING;
}
if (mQueueState == PollingQueueState.FETCHING)
Remove these lines, the break;, and the matching closing brace.
I'm trying, for academic purpose, to implement something similar to Java high level locks, using the low level mechanism.
I want to implement a different semantics, in which the signaler thread has to wait until the signaled terminates its critical regional, but when the signaled terminates, the signaler has the precedence in order to get the lock.
My doubt is the following: in the attached code, the presence of two adjacent synchronized block is a problem?
I tried to solve the problem used the boolean modified in the synchronized sections, but because the sections locked on different things, I'm not sure about this solution.
public class FIFOLock {
private final Queue<QueueElement> entrySet;
private boolean busy;
private Thread owner;
protected Queue<Object> urgentQueue;
public FIFOLock() {
this.entrySet = new LinkedList();
this.urgentQueue = new LinkedList();
this.busy = false;
this.owner = null;
}
public void lock() throws InterruptedException {
QueueElement queued;
synchronized (this) {
if ((owner != null) && (owner.equals(Thread.currentThread())))
return; /* Lock already achieved */
if (!busy) {
busy = true;
this.owner = Thread.currentThread();
System.out.println("LockOwner: " + Thread.currentThread().getName());
// System.out.println("FREE");
return;
}
queued = new QueueElement(true);
entrySet.add(queued);
}
synchronized (queued) {
if (queued.isWaiting())
queued.wait();
this.owner = Thread.currentThread();
}
}
public void unlock() throws InterruptedException {
Object urgentElement = new Object();
QueueElement entryElement = new QueueElement(false);
boolean urgent = false;
synchronized (this) {
if (urgentQueue.size() != 0) {
urgentElement = urgentQueue.poll();
urgent = true;
} else {
if (entrySet.size() == 0) {
busy = false;
return;
}
entryElement = entrySet.poll();
}
}
if (urgent) {
synchronized (urgentElement) {
urgentElement.notify();
}
} else {
synchronized (entryElement) {
owner = null;
if (entryElement.isWaiting())
entryElement.notify();
entryElement.setWaiting(false);
}
}
}
}
The code below allows us to run a job while ensuring that only one job at a time can run by using ReentrantLock.
Is there any way to modify this code to run job.call() asynchronously and to return the MyConcurrentJobException to the client prior to starting the thread?
We tried wrapping the try/catch/finally block in a new Thread but the unlock and lock have to happen in the same thread so we get an IllegalMonitorException
??
final static Lock lock = new ReentrantLock();
public Object runJob(String desc, Callable job, boolean wait) {
logger.info("Acquiring lock");
if (!lock.tryLock()) {
throw new MyConcurrentJobException();
}
activeJob = new JobStatus(desc);
logger.info("Lock acquired");
try {
return job.call();
} catch (MarginServiceAssertionException e) {
throw e;
} catch (MarginServiceSystemException e) {
throw e;
} catch (Exception e) {
throw new MarginServiceSystemException(e);
} finally {
activeJob = null;
logger.info("Releasing lock");
lock.unlock();
logger.info("Lock released");
}
}
You can use Semaphore instead of ReentrantLock, its permits are not bound to thread.
Something like this (not sure what you want to do with the result of job.call() in the asynchronous case):
final static Semaphore lock = new Semaphore(1);
public void runJob(String desc, Callable job, boolean wait) {
logger.info("Acquiring lock");
if (!lock.tryAcquire()) {
throw new MyConcurrentJobException();
}
startThread(new Runnable() {
public void run() {
try {
job.call();
} finally {
lock.release();
}
}
});
}
I think I am misunderstanding completely because to block and wait while doing something asynchronously doesn't make too much sense to me unless some progress can be made on the invoking thread.
Could you do something like this:
final static Lock lock = new ReentrantLock();
final static ExecutorService service = Executors.newThreadPoolExecutor();
public Object runJob(String desc, Callable job, boolean wait) {
logger.info("Acquiring lock");
if (!lock.tryLock()) {
throw new MyConcurrentJobException();
}
activeJob = new JobStatus(desc);
logger.info("Lock acquired");
try {
Future<?> future = service.submit(job);
// This next line will block until the job is finished
// and also will hold onto the lock.
boolean finished = false;
Object o = null;
while(!finished) {
try {
o = future.get(300, TimeUnit.MILLISECONDS);
finished = true;
catch(TimeOutException e) {
// Do some periodic task while waiting
// foot.tapLots();
}
}
if (o instanceof MarginServiceAssertionException) {
throw ((MargineServiceAssertionException)o);
} else if (o instanceof MargineServiceSystemException) {
throw ((MarginServiceSystemException)o);
} else if (o instanceof Exception) {
throw new MarginServiceSystemException(e);
}
} catch (... InterruptedException e) { /// catch whatever exceptions throws as part of this
/// Whatever needs to be done.
} finally {
activeJob = null;
logger.info("Releasing lock");
lock.unlock();
logger.info("Lock released");
}
}