The class is dangerous in a multithreading scenario because both methods can be called simultaneously, so the value of val (which is not atomic—it's updated in multiple steps) could be undefined—a classic race condition. You can, of course, use synchronization to solve this problem, which in this trivial case is easy. But once the class becomes realistically complex, synchronization can become very difficult. [5]

To rewrite this class as an active object you could do the following:

classMyActiveObject{privatedoubleval=0.0;privateBlockingQueue<Runnable>dispatchQueue=newLinkedBlockingQueue<Runnable>();publicMyActiveObject(){newThread(newRunnable(){@Overridepublicvoidrun(){while(true){try{dispatchQueue.take().run();}catch(InterruptedExceptione){// okay, just terminate the dispatcher}}}}).start();}voiddoSomething()throwsInterruptedException{dispatchQueue.put(newRunnable(){@Overridepublicvoidrun(){val=1.0;}});}voiddoSomethingElse()throwsInterruptedException{dispatchQueue.put(newRunnable(){@Overridepublicvoidrun(){val=2.0;}});}}

publicclassMyClass{privatedoubleval;// container for tasks// decides which request to execute next // asyncMode=true means our worker thread processes its local task queue in the FIFO order // only single thread may modify internal stateprivatefinalForkJoinPoolfj=newForkJoinPool(1,ForkJoinPool.defaultForkJoinWorkerThreadFactory,null,true);// implementation of active object methodpublicvoiddoSomething()throwsInterruptedException{fj.execute(()->{val=1.0;});}// implementation of active object methodpublicvoiddoSomethingElse()throwsInterruptedException{fj.execute(()->{val=2.0;});}}