Network Thread to communicate with UI Thread - java

I've created a class for multi threading in a Java application.
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class AppThreads {
private static final Object LOCK = new Object();
private static AppThreads sInstance;
private final Executor diskThread;
private final Executor uiThread;
private final Executor networkThread;
private AppExecutors(Executor diskThread, Executor networkThread, Executor uiThread) {
this.diskThread = diskThread;
this.networkThread = networkThread;
this.uiThread = uiThread;
}
public static AppExecutors getInstance() {
if (sInstance == null) {
synchronized (LOCK) {
sInstance = new AppExecutors(Executors.newSingleThreadExecutor(), Executors.newFixedThreadPool(4),
new MainThreadExecutor());
}
}
return sInstance;
}
public Executor diskThread() {
return diskThread;
}
public Executor networkThread() {
return networkThread;
}
private static class MainThreadExecutor implements Executor {
#Override
public void execute(Runnable command) {
command.run();
}
}
}
I am initiating a different thread as
public void getUsers(AppThreads executors) {
executors.networkThread().execute(() -> {
//Some DB operations
//getting server response code
HttpURLConnection con = (HttpURLConnection) url.openConnection();
...
...
..
int response=con.getResponseCode();
}
}
How uiThread will know the value of int response which is being executed in networkThread?

One simple solution: create some kind of callback, for example:
public interface Callback
{
void done(int response);
}
Pass the callback to your getUsers method. When you get your response code, you are able to call callback.done(response).
An alternative would be to create some kind of event / listener as #Jure mentionend.

Related

Converting code using AsyncTask to use Executor Service

I am having below code that uses AsyncTask to do some task in background but i would like to migrate to ExecutorService, the problem i am having is that my AsyncTask class has a constructor
Below is my AsyncTask method
private static class UpdateCustomerAsyncTask extends AsyncTask<Customer, Void, Void>{
private CustomerDao customerDao;
public UpdateCustomerAsyncTask(CustomerDao customerDao) {
this.customerDao = customerDao;
}
#Override
protected Void doInBackground(Customer... customers) {
try{
customerDao.updateCustomer(customers[0]);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
The above class is supposed to do the task of updating room database in background
I know how use Executor Service in a simple way but i would like some help when using the ExecutorService with a class which extends the Executor Service like the above way where i have extended AsyncTask
Below is how i tried implementing using Simple Executor Service but i am stuck when extending the Executor Service with a class
int NUMBER_OF_THREADS = 4;
ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
executorService.execute(() -> {
customerDao.updateCustomer(customers[0]);
});
For Executors i think below class is solve your problem and really help full while working with room. Check below
public class AppExecutors {
private final Executor mDiskIO;
private final Executor mNetworkIO;
private final Executor mMainThread;
private AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread) {
this.mDiskIO = diskIO;
this.mNetworkIO = networkIO;
this.mMainThread = mainThread;
}
public AppExecutors() {
this(Executors.newSingleThreadExecutor(), Executors.newFixedThreadPool(3),
new MainThreadExecutor());
}
public Executor diskIO() {
return mDiskIO;
}
public Executor networkIO() {
return mNetworkIO;
}
public Executor mainThread() {
return mMainThread;
}
private static class MainThreadExecutor implements Executor {
private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
#Override
public void execute(#NonNull Runnable command) {
mainThreadHandler.post(command);
}
}
}
And to update your custom use like this.
void updateCustomer(Integer id, Activity context){
YourDatabase database = YourDatabase.getDatabase(context)
AppExecutors appExecutors = new AppExecutors();
appExecutors.getInstance().diskIO().execute(new Runnable() {
#Override
public void run() {
database.customerDao.updateCustomer(customers[id]);
}
});
}

LMAX Disruptor Producer Incorrectly Wraparound + Overwrite Before Consumer Completes Read

I am recently introduced to the LMAX Disruptor and decided to give it a try. Thanks to the developers, the setup was quick and hassle free. But I think I am running into an issue if someone can help me with it.
The issue:
I was told that when the producer publish the event, it should block until the consumer had a chance to retrieve it before wrapping around. I have a sequence barrier on the consumer side and I can confirm that if there is no data published by the producer, the consumer's waitFor call will block. But, producer doesn't seem to be regulated in any way and will just wraparound and overwrite unprocessed data in the ring buffer.
I have a producer as a runnable object running on separate thread.
public class Producer implements Runnable {
private final RingBuffer<Event> ringbuffer;
public Producer(RingBuffer<Event> rb) {
ringbuffer = rb;
}
public void run() {
long next = 0L;
while(true) {
try {
next = ringbuffer.next();
Event e = ringbuffer.get(next);
... do stuff...
e.set(... stuff...);
}
finally {
ringbuffer.publish(next);
}
}
}
}
I have a consumer running on the main thread.
public class Consumer {
private final ExecutorService exec;
private final Disruptor<Event> disruptor;
private final RingBuffer<Event> ringbuffer;
private final SequenceBarrier seqbar;
private long seq = 0L;
public Consumer() {
exec = Executors.newCachedThreadPool();
disruptor = new Disruptor<>(Event.EVENT_FACTORY, 1024, Executors.defaultThreadFactory());
ringbuffer = disruptor.start();
seqbar = ringbuffer.newBarrier();
Producer producer = new Producer(ringbuffer);
exec.submit(producer);
}
public Data getData() {
seqbar.waitFor(seq);
Event e = ringbuffer.get(seq);
seq++;
return e.get();
}
}
Finally, I run the code like so:
public class DisruptorTest {
public static void main(String[] args){
Consumer c = new Consumer();
while (true) {
c.getData();
... Do stuff ...
}
}
You need to add a gating sequence (com.lmax.disruptor.Sequence) to the ringBuffer, this sequence must be updated on what point your consumer is.
You can implement your event handling with EventHandler interface and using the provided BatchEventProcessor(com.lmax.disruptor.BatchEventProcessor.BatchEventProcessor) which comes with builtin sequence
Here's a fully working example
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.lmax.disruptor.BatchEventProcessor;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import com.lmax.disruptor.dsl.Disruptor;
public class Main {
static class Event {
int id;
}
static class Producer implements Runnable {
private final RingBuffer<Event> ringbuffer;
public Producer(RingBuffer<Event> rb) {
ringbuffer = rb;
}
#Override
public void run() {
long next = 0L;
int id = 0;
while (true) {
try {
next = ringbuffer.next();
Event e = ringbuffer.get(next);
e.id = id++;
} finally {
ringbuffer.publish(next);
}
}
}
}
static class Consumer {
private final ExecutorService exec;
private final Disruptor<Event> disruptor;
private final RingBuffer<Event> ringbuffer;
private final SequenceBarrier seqbar;
private BatchEventProcessor<Event> processor;
public Consumer() {
exec = Executors.newCachedThreadPool();
disruptor = new Disruptor<>(() -> new Event(), 1024, Executors.defaultThreadFactory());
ringbuffer = disruptor.start();
seqbar = ringbuffer.newBarrier();
processor = new BatchEventProcessor<Main.Event>(
ringbuffer, seqbar, new Handler());
ringbuffer.addGatingSequences(processor.getSequence());
Producer producer = new Producer(ringbuffer);
exec.submit(producer);
}
}
static class Handler implements EventHandler<Event> {
#Override
public void onEvent(Event event, long sequence, boolean endOfBatch) throws Exception {
System.out.println("Handling event " + event.id);
}
}
public static void main(String[] args) throws Exception {
Consumer c = new Consumer();
while (true) {
c.processor.run();
}
}
}

Multithreading and Selenium

I am trying to open a set of links in different WebChrome drivers (atcThread[]) as fast as possible. I tried implementing ExecutorService but realized that the initial execution of the threads are sequential. Is there a way I could open up the links in parallel to be more faster. Thanks!
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ATC {
private ExecutorService executor = Executors.newFixedThreadPool(15);
public void startThreads() {
for (int i = 0; i < Captcha.x; i++) {
executor.execute(new ATCpool(i, Generator.links[i]));
}
}
private final class ATCpool implements Runnable{
public ATCpool(int x, String link){
Generator.atcThread[x].get(link);
}
#Override
public void run() {
// TODO Auto-generated method stub
}
}
}
For me you get this behavior because you call the method get(String url) in the constructor of your class ATCpool instead of calling it into the run method to delegate its call to the thread pool as you expect.
Simply change your class ATCpool for something like this:
private final class ATCpool implements Runnable {
private final int x;
private final String link;
ATCpool(int x, String link){
this.x = x;
this.link = link;
}
#Override
public void run() {
// Will be called asynchronously by a thread of the thread pool
Generator.atcThread[x].get(link);
}
}

Concurrent tests: test case scenario automatization

Task definition: I need to test custom concurrent collection or some container which manipulates with collections in concurrent environment. More precisely - I've read-API and write-API. I should test if there is any scenarios where I can get inconsistent data.
Problem: All concurrent test frameworks (like MultiThreadedTC, look at MultiThreadedTc section of my question) just provides you an ability to control the asynchronous code execution sequence. I mean you should suppose a critical scenarios by your own.
Broad question: Is there frameworks that can take annotations like #SharedResource, #readAPI, #writeAPI and check if your data will always be consistent? Is that impossible or I just leak a startup idea?
Annotation: If there is no such framework, but you find the idea attractive, you are welcome to contact me or propose your ideas.
Narrow question: I'm new in concurrency. So can you suggest which scenarios should I test in the code below? (look at PeerContainer class)
PeerContainer:
public class PeersContainer {
public class DaemonThreadFactory implements ThreadFactory {
private int counter = 1;
private final String prefix = "Daemon";
#Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, prefix + "-" + counter);
thread.setDaemon(true);
counter++;
return thread;
}
}
private static class CacheCleaner implements Runnable {
private final Cache<Long, BlockingDeque<Peer>> cache;
public CacheCleaner(Cache<Long, BlockingDeque<Peer>> cache) {
this.cache = cache;
Thread.currentThread().setDaemon(true);
}
#Override
public void run() {
cache.cleanUp();
}
}
private final static int MAX_CACHE_SIZE = 100;
private final static int STRIPES_AMOUNT = 10;
private final static int PEER_ACCESS_TIMEOUT_MIN = 30;
private final static int CACHE_CLEAN_FREQUENCY_MIN = 1;
private final static PeersContainer INSTANCE;
private final Cache<Long, BlockingDeque<Peer>> peers = CacheBuilder.newBuilder()
.maximumSize(MAX_CACHE_SIZE)
.expireAfterWrite(PEER_ACCESS_TIMEOUT_MIN, TimeUnit.MINUTES)
.removalListener(new RemovalListener<Long, BlockingDeque<Peer>>() {
public void onRemoval(RemovalNotification<Long, BlockingDeque<Peer>> removal) {
if (removal.getCause() == RemovalCause.EXPIRED) {
for (Peer peer : removal.getValue()) {
peer.sendLogoutResponse(peer);
}
}
}
})
.build();
private final Striped<Lock> stripes = Striped.lock(STRIPES_AMOUNT);
private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, new DaemonThreadFactory());
private PeersContainer() {
scheduledExecutorService.schedule(new CacheCleaner(peers), CACHE_CLEAN_FREQUENCY_MIN, TimeUnit.MINUTES);
}
static {
INSTANCE = new PeersContainer();
}
public static PeersContainer getInstance() {
return INSTANCE;
}
private final Cache<Long, UserAuthorities> authToRestore = CacheBuilder.newBuilder()
.maximumSize(MAX_CACHE_SIZE)
.expireAfterWrite(PEER_ACCESS_TIMEOUT_MIN, TimeUnit.MINUTES)
.build();
public Collection<Peer> getPeers(long sessionId) {
return Collections.unmodifiableCollection(peers.getIfPresent(sessionId));
}
public Collection<Peer> getAllPeers() {
BlockingDeque<Peer> result = new LinkedBlockingDeque<Peer>();
for (BlockingDeque<Peer> deque : peers.asMap().values()) {
result.addAll(deque);
}
return Collections.unmodifiableCollection(result);
}
public boolean addPeer(Peer peer) {
long key = peer.getSessionId();
Lock lock = stripes.get(key);
lock.lock();
try {
BlockingDeque<Peer> userPeers = peers.getIfPresent(key);
if (userPeers == null) {
userPeers = new LinkedBlockingDeque<Peer>();
peers.put(key, userPeers);
}
UserAuthorities authorities = restoreSession(key);
if (authorities != null) {
peer.setAuthorities(authorities);
}
return userPeers.offer(peer);
} finally {
lock.unlock();
}
}
public void removePeer(Peer peer) {
long sessionId = peer.getSessionId();
Lock lock = stripes.get(sessionId);
lock.lock();
try {
BlockingDeque<Peer> userPeers = peers.getIfPresent(sessionId);
if (userPeers != null && !userPeers.isEmpty()) {
UserAuthorities authorities = userPeers.getFirst().getAuthorities();
authToRestore.put(sessionId, authorities);
userPeers.remove(peer);
}
} finally {
lock.unlock();
}
}
void removePeers(long sessionId) {
Lock lock = stripes.get(sessionId);
lock.lock();
try {
peers.invalidate(sessionId);
authToRestore.invalidate(sessionId);
} finally {
lock.unlock();
}
}
private UserAuthorities restoreSession(long sessionId) {
BlockingDeque<Peer> activePeers = peers.getIfPresent(sessionId);
return (activePeers != null && !activePeers.isEmpty()) ? activePeers.getFirst().getAuthorities() : authToRestore.getIfPresent(sessionId);
}
public void resetAccessedTimeout(long sessionId) {
Lock lock = stripes.get(sessionId);
lock.lock();
try {
BlockingDeque<Peer> deque = peers.getIfPresent(sessionId);
peers.invalidate(sessionId);
peers.put(sessionId, deque);
} finally {
lock.unlock();
}
}
}
MultiThreadedTC test case sample: [optional section of question]
public class ProducerConsumerTest extends MultithreadedTestCase {
private LinkedTransferQueue<String> queue;
#Override
public void initialize() {
super.initialize();
queue = new LinkedTransferQueue<String>();
}
public void thread1() throws InterruptedException {
String ret = queue.take();
}
public void thread2() throws InterruptedException {
waitForTick(1);
String ret = queue.take();
}
public void thread3() {
waitForTick(1);
waitForTick(2);
queue.put("Event 1");
queue.put("Event 2");
}
#Override
public void finish() {
super.finish();
assertEquals(true, queue.size() == 0);
}
}
Sounds like a job for static analysis, not testing, unless you have time to run multiple trillions of test cases. You pretty much can't test multithreaded behaviour - test behaviour in a single thread, then prove the abscence of threading bugs.
Try:
http://www.contemplateltd.com/threadsafe
http://checkthread.org/

FutureTask with Callable that references the FutureTask

I have a situation where I need to create a FutureTask with a Callable that checks if it's owner has been cancelled. The code I have looks like this:
public static FutureTask<Result> makeFuture(final Call call, final TaskCompletionCallback completion) {
return new FutureTask<Result>(new Callable<Result>() {
#Override
public Result call() throws Exception {
Result result = CYLib.doNetworkRequest(call, new CarryOnCallback() {
#Override
public boolean shouldCarryOn() {
return !FutureTask.isDone();
}
});
return result;
}
});
}
Basically the doNetworkRequest asks the CarryOnCallback if it should continue at certain times during the operation. I would like for this callback to see if the FutureTask that is calling the doNetworkRequest was cancelled, which involves querying the actual FutureTask object.
Now I know that you can't really access 'this' because it hasn't been constructed yet. But is there a way around this, or a better design for my situation?
Cheers
EDIT:
Ok so I'm going about it like this now. Made a custom Callable and FutureTask. The Callable holds a reference to the FutureTask and this can be set manually after creating a new Callable:
public static MyTask makeMyTask(final Call call, final TaskCompletionCallback completion) {
MyTask task = null;
MyTask.InnerCallable innerCallable = new MyTask.InnerCallable(call, completion);
task = new MyTask(innerCallable);
innerCallable.setParent(task);
return task;
}
And just for reference, the InnerCallable looks like this:
public static class MyTask extends FutureTask<Result> {
InnerCallable callable;
public MyTask(InnerCallable callable) {
super(callable);
this.callable = callable;
}
private static class InnerCallable implements Callable<Result> {
private final Call call;
private final TaskCompletionCallback completion;
private WeakReference<MyTask> parentTask;
InnerCallable(Call call, TaskCompletionCallback completion) {
this.call = call;
this.completion = completion;
}
#Override
public Result call() {
Result result = CYLib.doNetworkRequest(this.call, new CarryOnCallback() {
#Override
public boolean shouldCarryOn() {
MyTask task = parentTask.get();
return !(task == null || task.isCancelled());
}
});
return result;
}
private void setParent(MyTask parentTask) {
this.parentTask = new WeakReference<MyTask>(parentTask);
}
}
}
So, your CYLib.doNetworkRequest() is working in another thread?
private static Map<Call,FutureTask> map=new HashMap();
public static FutureTask<Result> makeFuture(final Call call, final TaskCompletionCallback completion) {
FutureTask<Result> futureResult = new FutureTask<Result>(new Callable<Result>() {
#Override
public Result call() throws Exception {
Result result = CYLib.doNetworkRequest(call, new CarryOnCallback() {
#Override
public boolean shouldCarryOn() {
return !map.get(call).isCancelled();
}
});
return result;
}
});
map.put(call,futureResult);
return futureResult;
}

Categories

Resources