How to implement cancellable worker thread - multithreading

I'm trying to implement a cancellable worker thread using the new threading constructs in System.Threading.Tasks namespace.
So far I have have come up with this implementation:
public sealed class Scheduler
{
private CancellationTokenSource _cancellationTokenSource;
public System.Threading.Tasks.Task Worker { get; private set; }
public void Start()
{
_cancellationTokenSource = new CancellationTokenSource();
Worker = System.Threading.Tasks.Task.Factory.StartNew(
() => RunTasks(_cancellationTokenSource.Token),
_cancellationTokenSource.Token
);
}
private static void RunTasks(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
Thread.Sleep(1000); // simulate work
}
}
public void Stop()
{
try
{
_cancellationTokenSource.Cancel();
Worker.Wait(_cancellationTokenSource.Token);
}
catch (OperationCanceledException)
{
// OperationCanceledException is expected when a Task is cancelled.
}
}
}
When Stop() returns I expect Worker.Status to be TaskStatus.Canceled.
My unit tests have shown that under certain conditions Worker.Status remains set to TaskStatus.Running.
Is this a correct way to implement a cancellable worker thread?

I believe that the problem is in your call to
Worker.Wait(_cancellationTokenSource.Token);
That's waiting for the token to be signalled - which it already is, because you've just called Cancel(). If you change that to just
Worker.Wait();
then I believe you'll see a state of RanToCompletion. You won't see Canceled, because your task isn't throwing OperationCanceledException. If you change your RunTasks method to call
cancellationToken.ThrowIfCancellationRequested()
at the end, then you'll need to catch an AggregateException in Stop - but then you'll see a state of Canceled at the end.
At least, that's what my experimentation shows :)

Related

how to do something when liferay module stop

i am making cron job like loop to do something using new thread.
when module stop, this thread keeps running, so when i deployed updated module, i'm afraid it will make duplicate thread doing similar task
#Component(immediate = true, service = ExportImportLifecycleListener.class)
public class StaticUtils extends Utils{
private StaticUtils() {}
private static class SingletonHelper{
private static final StaticUtils INSTANCE = new StaticUtils();
}
public static StaticUtils getInstance() {
return SingletonHelper.INSTANCE;
}
}
public class Utils extends BaseExportImportLifecycleListener{
public Utils() {
startTask();
}
protected Boolean CRON_START = true;
private void startTask() {
new Thread(new Runnable() {
public void run() {
while (CRON_START) {
System.out.println("test naon bae lah ");
}
}
}).start();
}
#Deactivate
protected void deactivate() {
CRON_START = false;
System.out.println(
"cron stop lah woooooooooooooooooy");
}
}
i'm using liferay 7
I have populated task that i store from db, so this thread is checking is there a task that it must do, then if it exist execute it.
I'm quite new in osgi and liferay. i've try to use scheduler and failed and also exportimportlifecycle listener but dont really get it yet
think again: Do you really need something to run all the time in the background, or do you just need some asynchronous processing in the background, when triggered? It might be better to start a background task as a one-off, that automatically terminates
Liferay provides an internal MessageBus, that you can utilize to listen to events and implement background processing, without the need for a custom thread
You're in the OSGi world, so you can utilize #Activate, #Modified, #Deactivate (from org.osgi.service.component.annotations) or use a org.osgi.framework.BundleActivator.
But, in general, it's preferable if you don't start your own thread

Spring boot multithreaded async not working

The task is to call a database, retrieve certain records update and save them.
As the amount of records if fairly large we want to do this Async, however, this doesn't seem to be implemented correctly.
The main class:
#SpringBootApplication
#EnableAsync
MainApplication() {
#Bean("threadPoolExecutor")
public TaskExecutor getAsyncExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(DataSourceConfig.getTHREAD_POOL_SIZE());
executor.setMaxPoolSize(DataSourceConfig.getTHREAD_POOL_SIZE());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setThreadNamePrefix("RetryEnhancement-");
return executor;
}
}
Method in the first service:
#Service
public class FirstService() {
#Transactional
public void fullProcess() {
for(int counter = 0; counter < ConfigFile.getTHREADS(); counter++){
secondaryService.threads();
}
}
}
Method in the second service:
#Service
public class SecondService () {
#Async("threadPoolExecutor")
public void threads() {
while(thirdService.threadMethod()) {
//doNothing
}
}
}
Method in the third service:
#Service
public class ThirdService() {
#Transactional
public boolean threads() {
Record record = repository.fetchRecord();
if(record!=null) {
updateRecord(record);
saveRecord(record);
return true;
} else {
return false;
}
}
}
Repository:
public interface repository extends CrudRepository<Record, long> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
Record fetchRecord();
}
The issue I'm finding is that, while the code executes perfectly fine, it seems to have a Synchronous execution (found by adding a .sleep and watching the execution in the logger).
The seperate threads seem to be waiting until the other is executed.
I'm probably doing something wrong and if another thread already explains the issue, than please refer it, though I have not been able to find this issue in a different thread.
Your solution is way to complex. Ditch all of that and just inject the TaskExecutor and do the updateRecord in a separate thread (you might need to retrieve it again as you are now using a different thread and thus connection.
Something like this should do the trick
private final TaskExecutor executor; // injected through constructor
public void process() {
Stream<Record> records = repository.fetchRecords(); // Using a stream gives you a lazy cursor!
records.forEach(this::processRecord);
}
private void processRecord(Record record) {
executor.submit({
updateRecord(record);
saveRecord(record);
});
}
You might want to put the processRecord into another object and make it #Transactional or wrap it in a TransactionTemplate to get that behavior.

On servlet 3.0 webserver, is it good to make all servlets and filters async?

I am confused with Async feature introduced in Servlet 3.0 spec
From Oracle site (http://docs.oracle.com/javaee/7/tutorial/doc/servlets012.htm):
To create scalable web applications, you must ensure that no threads
associated with a request are sitting idle, so the container can use
them to process new requests.
There are two common scenarios in which a thread associated with a
request can be sitting idle.
1- The thread needs to wait for a resource to become available or process data before building the response. For example, an application
may need to query a database or access data from a remote web service
before generating the response.
2- The thread needs to wait for an event before generating the response. For example, an application may have to wait for a JMS
message, new information from another client, or new data available in
a queue before generating the response.
The first item happens a lot (nearly always, we always query db or call a remote webservice to get some data). And calling an external resource will always consume some time.
Does it mean that we should ALWAYS use servelt async feature for ALL our servelts and filter ?!
I can ask this way too, if I write all my servelts and filters async, will I lose anything (performance)?!
If above is correct the skeleton of ALL our servlets will be:
public class Work implements ServletContextListener {
private static final BlockingQueue queue = new LinkedBlockingQueue();
private volatile Thread thread;
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
thread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
ServiceFecade.doBusiness();
AsyncContext context;
while ((context = queue.poll()) != null) {
try {
ServletResponse response = context.getResponse();
PrintWriter out = response.getWriter();
out.printf("Bussiness done");
out.flush();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
context.complete();
}
}
} catch (InterruptedException e) {
return;
}
}
}
});
thread.start();
}
public static void add(AsyncContext c) {
queue.add(c);
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
thread.interrupt();
}
}

Java: Running transaction in multithreaded environment

We are launching a website that will have a very heavy volume for a short period of time. It is basically giving tickets. The code is written in Java, Spring & Hibernate. I want to mimic the high volume by spawning multiple threads and trying to get the ticket using JUnit test case. The problem is that in my DAO class the code just simply dies after I begin transaction. I mean there is no error trace in the log file or anything like that. Let me give some idea about the way my code is.
DAO code:
#Repository("customerTicketDAO")
public class CustomerTicketDAO extends BaseDAOImpl {// BaseDAOImpl extends HibernateDaoSupport
public void saveCustomerTicketUsingJDBC(String customerId) {
try{
getSession().getTransaction().begin(); //NOTHING HAPPENS AFTER THIS LINE OF CODE
// A select query
Query query1 = getSession().createSQLQuery("my query omitted on purpose");
.
.
// An update query
Query query2 = getSession().createSQLQuery("my query omitted on purpose");
getSession().getTransaction().commite();
} catch (Exception e) {
}
}
Runnable code:
public class InsertCustomerTicketRunnable implements Runnable {
#Autowired
private CustomerTicketDAO customerTicketDAO;
public InsertCustomerTicketRunnable(String customerId) {
this.customerId = customerId;
}
#Override
public void run() {
if (customerTicketDAO != null) {
customerTicketDAO.saveCustomerTicketUsingJDBC(customerId);
}
}
}
JUnit method:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"file:src/test/resources/applicationContext-test.xml"})
public class DatabaseTest {
#Before
public void init() {
sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
customerTicketDAO = (CustomerTicketDAO)applicationContext.getBean("customerTicketDAO");
}
#After
public void end() throws Exception {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(session);
}
#Test
public void saveCustomerTicketInMultipleThreads () throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
for (int i=0; i<1000; i++) {
executor.submit(new InsertCustomerTicketRunnable(i));
}
// This will make the executor accept no new threads
// and finish all existing threads in the queue
executor.shutdown();
// Wait until all threads are finish
executor.awaitTermination(1, TimeUnit.SECONDS);
}
I see no data being inserted into the database. Can someone please point me as to where I am going wrong?
Thanks
Raj
SessionFactory is thread safe but Session is not. So my guess is that you need to call SessionFactoryUtils.getSession() from within each thread, so that each thread gets its own instance. You are currently calling it from the main thread, so all children threads try to share the same instance.
Naughty, naughty!
public void saveCustomerTicketUsingJDBC(String customerId) {
try {
getSession().getTransaction().begin(); //NOTHING HAPPENS AFTER THIS LINE OF CODE
.
.
} catch (Exception e) {
}
}
You should never (well, hardly ever) have an empty catch block, if there is a problem you will find that your code 'just simply dies' with no log messages. Oh look, that's what's happening ;)
At the very minimum you should log the exception, that will go a long way towards you helping you find what the problem is (and from there, the solution).

How to get an exception raised from a long running background Task without having main thread to wait

I want to perform some long running operation (e.g. listening to some event raised by OS) on the background thread. Most of the times, operation will run continuously without any problem. But in certain rare conditions, OS level API sends some error code and I need to raise exception from background thread which has to be propagated to the main thread to show it to the user of my WinFrom application.
I had decided to use BackgroundWorker for this. But .NET 4.0 provides Task class of the Task Parallel Library which is a better option as per various blogs on the TPL.
In my application, I have to kick off the background task before actual form is shown. Since actual code is quite complex, I have written some sample code simulating real time problem:
public static Task task;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ThreadTest tt = new ThreadTest();
task = new Task(() => tt.PerformTask("hi"));
task.Start();
try
{
task.Wait();
}
catch (AggregateException aggregateException)
{
// Handle exception here.
}
Application.Run(new Form1());
}
In this code, I never see the main form simply because background task keeps running without exception and task.Wait() call makes the current thread waiting until background task finishes!
Can I use TPL's Task for such scenarios where main thread should not wait until background task is finished but at the same time, it should get exception details whenever exception is raised from the background task?
In above code, one of the solutions could be to move the task creation code at some later stage. But my question is more academic in this case.
Yes you can. Please see the code below.
The program code is:
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Task longRunningTask = new Task((state) =>
{
LongRunningWork.DoWork( cancellationTokenSource.Token);
},cancellationTokenSource.Token,TaskCreationOptions.LongRunning);
var newForm = new Form1(cancellationTokenSource);
new Thread((state) =>
{
longRunningTask.Start();
try
{
longRunningTask.Wait();
}
catch (AggregateException exception)
{
Action<Exception> showError = (ex) => MessageBox.Show(state as Form, ex.Message);
var mainForm = state as Form;
if (mainForm != null)
{
mainForm.BeginInvoke(showError, exception.InnerException);
}
}
}).Start(newForm);
Application.Run(newForm);
And the code for the long running task is:
public class LongRunningWork
{
public static void DoWork( CancellationToken cancellationToken)
{
int iterationCount = 0;
//While the
while (!cancellationToken.IsCancellationRequested &&iterationCount <5)
{
//Mimic that we do some long jobs here
Thread.Sleep(1000);
iterationCount++;
//The jobs may throw the exception on the specific condition
if (iterationCount ==5)
{
throw new InvalidOperationException("Invalid action");
}
}
//cancel the task
cancellationToken.ThrowIfCancellationRequested();
}
}
Finally, the code for the Form1 which includes a exit button, whose function is to terminate the program on clicking.
public partial class Form1 : Form
{
private CancellationTokenSource _cancellationTokenSource;
public Form1()
{
InitializeComponent();
}
public Form1(CancellationTokenSource cancellationTokenSource):this()
{
_cancellationTokenSource = cancellationTokenSource;
}
private void exitBtn_Click(object sender, EventArgs e)
{
//Cancel out the task
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
}
//Exit the program
Application.Exit();
}
}
Start your long running operation from the form itself rather than before the form is created. Remember that Application.Run() starts a message loop on the current thread, but that means you can use that message loop to poll your task from the Timer class.
class Form1 : Form
{
private Timer PollingTimer;
private Task BackgroundTask;
public Form1()
{
InitializeComponent();
// Begin the background task.
ThreadTest tt = new ThreadTest();
this.BackgroundTask = new Task(() => tt.PerformTask("hi"));
this.BackgroundTask.Start();
// Monitor the task's status by polling it regularly.
this.PollingTimer = new Timer();
this.PollingTimer.Interval = 1000; // In milliseconds.
this.PollingTimer.Tick += timerCallback;
this.PollingTimer.Start();
}
private timerCallback(object sender, EventArgs e)
{
if (this.BackgroundTask.IsFaulted)
{
// Exception information is in BackgroundTask.Exception.
}
}
}
If you dislike polling (which I do), you'll need to catch the exception from your task and marshall it back to your UI thread. The best way to do that is simply not catch the exception in the task itself and provide a continuation method which will only execute on error.
class Form1 : Form
{
private Task BackgroundTask;
public Form1()
{
InitializeComponent();
// Capture the UI thread context.
// (Note, it may be safer to run this in the Form.Load event than the constructor.
var uiContext = TaskScheduler.FromCurrentSynchronizationContext();
// Begin the background task.
ThreadTest tt = new ThreadTest();
this.BackgroundTask = new Task(() => tt.PerformTask("hi"))
// Schedule a continuation to be executed after the task is completed.
.ContinueWith((t,arg) =>
{
// Exception information is in t.Exception
},null, null,
// Only execute the continuation if the task throws an exception.
TaskContinuationOptions.OnlyOnFaulted,
// Execute the continuation on the UI thread we captured above.
uiContext);
this.BackgroundTask.Start();
}
}
MSDN references for Task.ContinueWith() and TaskScheduler.FromCurrentSynchronizationContext().
And, if you have the luxury of .NET 4.5 with async and await:
class Form1 : Form
{
private Task BackgroundTask;
public Form1()
{
InitializeComponent();
}
private async void Form1_Load(object sender, EventArgs e)
{
ThreadTest tt = new ThreadTest();
try
{
// Move your Task creation and start logic into a method.
await tt.RunAsync();
}
catch (Exception ex)
{
// Really smart compiler writers make sure you're on the right thread
// and everything Just Works(tm).
}
}
}

Resources