android thread and handler best practices - java

I have the following class. The purpose of the class is to allow me to simulate a teletype/typewriter by displaying about ten characters a second.
The point of the CharacterLoopThread class is to look at the outputBuffer, and if there are any characters in it, invoke a runnable on the UI thread that pulls off the first character and plops it into the textView. The thread then sleeps for about 100ms. (There are some shenanigans here... while the teletype was amazing when I used it in 1979, it's a little slow for my tastes now. So every 10 characters, I reduce the delay slightly. When there are no more characters to display, I reset the delay to 100ms...)
I edited off the bottom of the class since it was not germane to my question.
What I have here seems to work well. However, does it work because of me or in spite of me? What are your preferred ways of writing Threads and Handlers?
public class MyActivity extends Activity {
private TextView textView;
private ScrollView scrollView;
private StringBuilder outputBuffer;
private Handler handler;
private CharacterLooperThread characterLooperThread;
(snip)
private class CharacterLooperThread extends Thread {
private boolean allowRun;
private Runnable run;
int effectiveCharacterDelay;
int characterCount;
public CharacterLooperThread() {
allowRun = true;
run = new Runnable() {
public void run() {
/**
* Don't do anything if the string has been consumed. This is necessary since when the delay
* is very small it is possible for a runnable to be queued before the previous runnable has
* consumed the final character from the outputBuffer. The 2nd runnable will cause an
* exception on the substring() below.
*/
if (outputBuffer.length() == 0) return;
try {
textView.append(outputBuffer.substring(0, 1));
scrollToBottom();
outputBuffer.deleteCharAt(0);
} catch (Exception e) {
toast(getMsg(e));
}
}
};
}
public void run() {
resetDelay();
while (allowRun) {
/**
* This if() performs 2 functions:
* 1. It prevents us from queuing useless runnables in the handler. Why use the resources if
* there's nothing to display?
* 2. It allows us to reset the delay values. If the outputBuffer is depleted we can reset the
* delay to the starting value.
*/
if (outputBuffer.length() > 0) {
handler.post(run);
reduceDelay();
} else {
resetDelay();
}
try {
Thread.sleep(effectiveCharacterDelay);
} catch (InterruptedException e) {
toast("sleep() failed with " + e.getMessage());
}
}
/**
* Make sure there's no runnable on the queue when the thread exits.
*/
handler.removeCallbacks(run);
}
public void exit() {
allowRun = false;
}

One idea is to use Handler.postDelayed to schedule the individual "keystrokes". You can either do this all at once, or have each keystroke Runnable schedule the next as it finishes; if processing gets behind schedule, the former approach will catch up as quickly as possible, while the latter will essentially push everything back to keep the same inter-keystroke delay.
It worries me to see one thread altering the StringBuilder while another reads it. (The StringBuilder class was a non-thread-safe successor to StringBuffer, which was written back in the day when folks thought making individual classes thread-safe was good design). If it doesn't occasionally do something unexpected, you're lucky, though not much can go wrong here. Using postDelayed, however, you might get rid of the background thread altogether.
As long as you are making anonymous Runnable classes, note that you can feed them arguments (as long you declare variable final). So I would tend to post one character at a time to each Runnable, like this:
long delay = 0;
for (int j = 0; j < outputBuffer.length(); ++j) {
final CharSequence s = outputBuffer.subSequence(j, j + 1);
handler.postDelayed(new Runnable() {
#Override public void run() {
textView.append(s);
scrollToBottom();
}
}, delay);
delay += 100; // or whatever
}

Related

Multithread Binary Semaphore's: Alternating Outputs

The goal is to have String of output's consisting of W's, X's ,y's
and z's.
W and X should alternate and W must always be ahead of X.
y and z must alternate with y always ahead of z.
The total of y's and z's must be less than the number of W's at any given point in the output.
My program so far satisfies the first two points but I'm having trouble with the last one. Also, I very new to semaphore's and want to know if the code I've implemented follows good practices. For example, I had originally set the initial value of my binary semaphores to 0,1,2,3 but changed it to 0,1,0,1 in order to satisfy the second condition.
public class BinarySemaphore extends Semaphore{
public BinarySemaphore(int initial) {
value = (initial>0) ? 1 : 0;
}
public synchronized void P() throws InterruptedException {
while (value==0) {
wait();
}
value = 0;
}
public synchronized void V() {
value = 1;
notify();
}
}
public class ProcessW extends App implements Runnable{
public void run() {
while (true) {
try {
Thread.sleep(1 + (int) (Math.random() * 500));
bsX.P();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.print("W");
bsW.V();
}
}
}
public class ProcessX extends App implements Runnable{
public void run() {
while (true) {
try {
Thread.sleep(1 + (int) (Math.random() * 500));
bsW.P();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.print("X");
bsX.V();
}
}
}
public class ProcessY extends App implements Runnable{
public void run() {
while (true) {
try {
Thread.sleep(1 + (int) (Math.random() * 800));
bsZ.P();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.print("y");
bsY.V();
}
}
}
public class ProcessZ extends App implements Runnable{
public void run() {
while (true) {
try {
Thread.sleep(1 + (int) (Math.random() * 800));
bsY.P();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.print("z");
bsZ.V();
}
}
}
public class App {
protected static final BinarySemaphore bsW = new BinarySemaphore(
0);
protected static final BinarySemaphore bsX = new BinarySemaphore(
1);
protected static final BinarySemaphore bsY = new BinarySemaphore(
0);
protected static final BinarySemaphore bsZ = new BinarySemaphore(
1);
public static void main(String[] args) throws Exception {
Thread W = new Thread(new ProcessW());
Thread X = new Thread(new ProcessX());
Thread Y = new Thread(new ProcessY());
Thread Z = new Thread(new ProcessZ());
W.start();
X.start();
Y.start();
Z.start();
Thread.sleep(3000);
System.out.println("");
System.exit(0);
}
}
Here is an example of what my program is currently outputting:
WXWyzXWXWXyzyWXWXzyzWXyzWXyzWX
Your goal is not defined very well because you didn't write what means are you required to use to achieve the goal. For instance, a program that always prints "WXyzWX" satisfies your question. But I'll assume you specifically want to use four threads each printing its own letter, and you want to use Semaphores for this.
Semaphores are used to manage a number of "permissions" between different threads. A thread can semaphore.acquire() a permission and semaphore.release() it after doing its job. If no permissions are available at the moment of calling acquire(), the thread waits until some other thread releases a permission. See documentation for details.
You can use Semaphores for your purpose, but before that I have to explain what "fairness" means in terms of multithreading. By default, the Semaphore (and all other Java concurrent stuff) is "unfair". This means that when a permission is released, it will be given to any of the threads that are waiting for one, considering the overall performance first. On the other hand, a "fair" Semaphore will always give a newly available permission to the thread that has been waiting for one for the longest time. This practically orders the threads as if in a queue. In general, fair structures work slower, but in our case this fairness is very useful.
Now to the idea. You can think of your letter ordering in a following way: to write X, a thread needs a permission that will only be available to it after another thread writes W, and then to write W you will need a permission from X thread. So you can use a semaphore for these two threads, with each thread acquiring and releasing a permission from the semaphore before and after printing the letter. And its fairness guarantees that W and X will always be alternating (don't forget that by default semaphores are unfair, you have to specify a flag in its constructor in order to make it fair). You should also make sure which thread acquires the permission first, or else you will get X always ahead of W.
You can make a similar trick to alternate y and z, but now you have to guarantee your third condition. This is also doable using a semaphore: to write a y or a z, you need a permission that can only be acquired after some W-s were written. I'm going to make you think this one through by yourself. Maybe a nice idea would be to randomly decide whether to release a permission or not, but no details here :)
I must mention that this is by far not the only way to accomplish your task, and also semaphores may be not the best tool to use in here. (I don't think a specific best one exists though.)
And now some extra comments on your code:
What exactly is your purpose of extending the java Semaphore? You never use any of its methods. You can just delete that 'extends' if you want to use this code.
To generate a random value from 0 to N, there is a nextInt(N) method in java.util.Random class. It suits your purposes better.
InterruptedException is one of the few ones that can be safely ignored most of the times (unless you know what it means and want to use it). I mention it because in case it is thrown, your output is going to be mixed up with letters and exceptions.
You simply create a thread, start it and then never access it. In this case, you can simplify your lines to new Thread(new ProcessW()).start() without even creating a variable.
P() and V() are terrible names for methods - I can barely understand what they are supposed to do.
What is the purpose of your BinarySemaphore fields in App class being protected? Did you mean private?
You're stopping all of your threads by calling System.exit(0). This way you cannot make a difference which threads to stop and which not to, as well as being unable to do anything after stopping the threads. A simple solution would be to create a volatile boolean isRunning = true; visible to all threads (do you know what volatile is?), replace while(true) to while(isRunning) and instead of calling System.exit() just do isRunning = false. Or else use the interruption mechanism (again, if you know what it is).

Java: How do I use the result of the first of multiple threads that complete?

I have a problem in Java where I want to spawn multiple concurrent threads simultaneously. I want to use the result of whichever thread/task finishes first, and abandon/ignore the results of the other threads/tasks. I found a similar question for just cancelling slower threads but thought that this new question was different enough to warrant an entirely new question.
Note that I have included an answer below based what I considered to be the best answer from this similar question but changed it to best fit this new (albeit similar) problem. I wanted to share the knowledge and see if there is a better way of solving this problem, hence the question and self-answer below.
You can use ExecutorService.invokeAny. From its documentation:
Executes the given tasks, returning the result of one that has completed successfully …. Upon normal or exceptional return, tasks that have not completed are cancelled.
This answer is based off #lreeder's answer to the question "Java threads - close other threads when first thread completes".
Basically, the difference between my answer and his answer is that he closes the threads via a Semaphore and I just record the result of the fastest thread via an AtomicReference. Note that in my code, I do something a little weird. Namely, I use an instance of AtomicReference<Integer> instead of the simpler AtomicInteger. I do this so that I can compare and set the value to a null integer; I can't use null integers with AtomicInteger. This allows me to set any integer, not just a set of integers, excluding some sentinel value. Also, there are a few less important details like the use of an ExecutorService instead of explicit threads, and the changing of how Worker.completed is set, because previously it was possible that more than one thread could finish first.
public class ThreadController {
public static void main(String[] args) throws Exception {
new ThreadController().threadController();
}
public void threadController() throws Exception {
int numWorkers = 100;
List<Worker> workerList = new ArrayList<>(numWorkers);
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(1);
//Semaphore prevents only one thread from completing
//before they are counted
AtomicReference<Integer> firstInt = new AtomicReference<Integer>();
ExecutorService execSvc = Executors.newFixedThreadPool(numWorkers);
for (int i = 0; i < numWorkers; i++) {
Worker worker = new Worker(i, startSignal, doneSignal, firstInt);
execSvc.submit(worker);
workerList.add(worker);
}
//tell workers they can start
startSignal.countDown();
//wait for one thread to complete.
doneSignal.await();
//Look at all workers and find which one is done
for (int i = 0; i < numWorkers; i++) {
if (workerList.get(i).isCompleted()) {
System.out.printf("Thread %d finished first, firstInt=%d\n", i, firstInt.get());
}
}
}
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
// null when not yet set, not so for AtomicInteger
private final AtomicReference<Integer> singleResult;
private final int id;
private boolean completed = false;
public Worker(int id, CountDownLatch startSignal, CountDownLatch doneSignal, AtomicReference<Integer> singleResult) {
this.id = id;
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.singleResult = singleResult;
}
public boolean isCompleted() {
return completed;
}
#Override
public void run() {
try {
//block until controller counts down the latch
startSignal.await();
//simulate real work
Thread.sleep((long) (Math.random() * 1000));
//try to get the semaphore. Since there is only
//one permit, the first worker to finish gets it,
//and the rest will block.
boolean finishedFirst = singleResult.compareAndSet(null, id);
// only set this if the result was successfully set
if (finishedFirst) {
//Use a completed flag instead of Thread.isAlive because
//even though countDown is the last thing in the run method,
//the run method may not have before the time the
//controlling thread can check isAlive status
completed = true;
}
}
catch (InterruptedException e) {
//don't care about this
}
//tell controller we are finished, if already there, do nothing
doneSignal.countDown();
}
}

Exact same code (with multithreading) doesn't work on 2 different computers

I'm working at the moment on a simple Chess A.I. (calculate possible future turns, rate them, chosse the best one, + some tricks so you don't have to calculate every single turn). The code is written in Java and I'm using Netbeans. To make the calculations faster, I use multithreading. The code works roughly like this:
Main function makes first some calculations and then starts 8 threads.
the threads execute the main-calculations
when they finish, they set a boolean value in a boolean array (finished[]) true. This array is in the "main Class" (if you call it like this), where also the main function is.
during all this time the main function is waiting and checking constantly if every value of the finished[] - array is true. If that is the case, it continues it's work.
Now I have a strange problem. The code works perfectly on my PC, but when I run the EXACT same code on my laptop, the main function won't continue its work, after all values of the finished[]-array are true. I already made some changes in the code, so I can try it with different numbers of threads, but the result is always the same.
I have totally no idea what's going on here and would really appreciate it, if someone of you had any answers and/or suggestions!
If you need any more Information just ask, I'll try my best. :)
(Sorry for possible grammar mistakes, english isn't my native language, but I'm trying my best. ;))
So I was asked to show some Code I used in the program:
(Perhaps first a warning, yes I am still a big Noob in Java and this is my first time I work with threads so don't be shocked if you see terrible mistakes I possibly made. xD)
The main Class looks something like this:
public class Chess_ai_20 {
static boolean finished[] = new boolean[8];
Distributor[] Distributors = new Distributor[8];
...
public static void main(String[] args) {
boolean testing=false;
...
//some calculations and other stuff
...
Distributors[0] = new Distributor(...., "0"); //the String "0" will be the thread name.
Distributors[1] = new ...
...
Distributors[7] = new Distributor(...., "7");
for (int i = 0; i < 8; i++) {
Distributoren[i].start();
}
testing=false;
while(testing==false){
if(finished[0]==true && finished[1]==true && ... && finished[7]==true){
testing=true; //That's the point where I get stuck I suppose
}
}
System.out.println("I made it!");
}
public static void setFinished(int i) {
finished[i] = true;
System.out.println("finished [" + i + "] = " + finished[i]);
System.out.println(Arrays.toString(finished)); //To check how many values already are true
}
}
Then we got of course the class "Distributor"
public class Distributor extends Thread {
Thread t;
String threadname;
boolean running=false;
...
Distributor(......, String s) {
threadname=s;
...
...
}
#Override
public void start() {
running=true;
if (t == null) {
t = new Thread(this,threadname);
t.start();
}
}
#Override
public void run() {
if(running){
...
//Do the main calculations etc.
...
//All the Calculations habe been done at this point
Chess_ai_20.setFinished(Character.getNumericValue(threadname.charAt(0))); //Set the value of finished[] true in the main class
running=false;
}
}
}
As others have mentioned, using a Future would be much simpler and easy to understand. Below is a snippet demonstrating how you could rewrite your code. Check out the code in action.
First, you write a Callable to define the task that you want to do.
public class MyCallable implements Callable<Boolean> {
#Override
public Boolean call() {
// Do some job and return the result.
return Boolean.TRUE;
}
}
And then, you submit this task to an Executor. There are a lot of Executors in JDK. You want to go through the Concurrency Tutorial first.
ExecutorService executor = Executors.newFixedThreadPool(Runtime
.getRuntime().availableProcessors());
List<Callable<Boolean>> callables = new ArrayList<>();
for (int counter = 0; counter < 8; counter++) {
callables.add(new MyCallable());
}
List<Future<Boolean>> futures = executor.invokeAll(callables);
for (Future<Boolean> future : futures) {
System.out.println(future.get()); // You'd want to store this into an array or wherever you see fit.
}
executor.shutdown();
Remember that the futures returned by the executor are in the same order as the Callables you submitted (or added) to the Collection (in this case, an ArrayList). So you don't need to worry about returning the index, an ID or even the name of the Thread (if you assigned one) to map the corresponding result.

Running time of a job sent to a ExecutorService

Good day,
I am writing a program where a method is called for each line read from a text file. As each call of this method is independent of any other line read I can call them on parallel. To maximize cpu usage I use a ExecutorService where I submit each run() call. As the text file has 15 million lines, I need to stagger the ExecutorService run to not create too many jobs at once (OutOfMemory exception). I also want to keep track of the time each submitted run has been running as I have seen that some are not finishing. The problem is that when I try to use the Future.get method with timeout, the timeout refers to the time since it got into the queue of the ExecutorService, not since it started running, if it even started. I would like to get the time since it started running, not since it got into the queue.
The code looks like this:
ExecutorService executorService= Executors.newFixedThreadPool(ncpu);
line = reader.readLine();
long start = System.currentTimeMillis();
HashMap<MyFut,String> runs = new HashMap<MyFut, String>();
HashMap<Future, MyFut> tasks = new HashMap<Future, MyFut>();
while ( (line = reader.readLine()) != null ) {
String s = line.split("\t")[1];
final String m = line.split("\t")[0];
MyFut f = new MyFut(s, m);
tasks.put(executorService.submit(f), f);
runs.put(f, line);
while (tasks.size()>ncpu*100){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Iterator<Future> i = tasks.keySet().iterator();
while(i.hasNext()){
Future task = i.next();
if (task.isDone()){
i.remove();
} else {
MyFut fut = tasks.get(task);
if (fut.elapsed()>10000){
System.out.println(line);
task.cancel(true);
i.remove();
}
}
}
}
}
private static class MyFut implements Runnable{
private long start;
String copy;
String id2;
public MyFut(String m, String id){
super();
copy=m;
id2 = id;
}
public long elapsed(){
return System.currentTimeMillis()-start;
}
#Override
public void run() {
start = System.currentTimeMillis();
do something...
}
}
As you can see I try to keep track of how many jobs I have sent and if a threshold is passed I wait a bit until some have finished. I also try to check if any of the jobs is taking too long to cancel it, keeping in mind which failed, and continue execution. This is not working as I hoped. 10 seconds execution for one task is much more than needed (I get 1000 lines done in 70 to 130s depending on machine and number of cpu).
What am I doing wrong? Shouldn't the run method in my Runnable class be called only when some Thread in the ExecutorService is free and starts working on it? I get a lot of results that take more than 10 seconds. Is there a better way to achieve what I am trying?
Thanks.
If you are using Future, I would recommend change Runnable to Callable and return total time in execution of thread as result. Below is sample code:
import java.util.concurrent.Callable;
public class MyFut implements Callable<Long> {
String copy;
String id2;
public MyFut(String m, String id) {
super();
copy = m;
id2 = id;
}
#Override
public Long call() throws Exception {
long start = System.currentTimeMillis();
//do something...
long end = System.currentTimeMillis();
return (end - start);
}
}
You are making your work harder as it should be. Java’s framework provides everything you want, you only have to use it.
Limiting the number of pending work items works by using a bounded queue, but the ExecutorService returned by Executors.newFixedThreadPool() uses an unbound queue. The policy to wait once the bounded queue is full can be implemented via a RejectedExecutionHandler. The entire thing looks like this:
static class WaitingRejectionHandler implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);// block until capacity available
} catch(InterruptedException ex) {
throw new RejectedExecutionException(ex);
}
}
}
public static void main(String[] args)
{
final int nCPU=Runtime.getRuntime().availableProcessors();
final int maxPendingJobs=100;
ExecutorService executorService=new ThreadPoolExecutor(nCPU, nCPU, 1, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(maxPendingJobs), new WaitingRejectionHandler());
// start flooding the `executorService` with jobs here
That’s all.
Measuring the elapsed time within a job is quite easy as it has nothing to do with multi-threading:
long startTime=System.nanoTime();
// do your work here
long elpasedTimeSoFar = System.nanoTime()-startTime;
But maybe you don’t need it anymore once you are using the bounded queue.
By the way the Future.get method with timeout does not refer to the time since it got into the queue of the ExecutorService, it refers to the time of invoking the get method itself. In other words, it tells how long the get method is allowed to wait, nothing more.

Java Puzzler: busy wait threads stop working

This is some sort of a Java Puzzler, that I stumbled across and can't really explain. Maybe somebody can?
The following program hangs after a short time. Sometimes after 2 outputs, sometimes after 80, but almost always before terminating correctly. You might have to run it a few times, if it doesn't happen the first time.
public class Main {
public static void main(String[] args) {
final WorkerThread[] threads = new WorkerThread[]{ new WorkerThread("Ping!"), new WorkerThread("Pong!") };
threads[0].start();
threads[1].start();
Runnable work = new Runnable() {
private int counter = 0;
public void run() {
System.out.println(counter + " : " + Thread.currentThread().getName());
threads[counter++ % 2].setWork(this);
if (counter == 100) {
System.exit(1);
}
}
};
work.run();
}
}
class WorkerThread extends Thread {
private Runnable workToDo;
public WorkerThread(String name) {
super(name);
}
#Override
public void run() {
while (true){
if (workToDo != null) {
workToDo.run();
workToDo = null;
}
}
}
public void setWork(Runnable newWork) {
this.workToDo = newWork;
}
}
Now, it's clear that busy waiting loops are not a great idea in general. But this not about improving, it's about understanding what is happening.
Since everything works as expected when WorkerThread.setWork() is synchronized or when the WorkerThread.workToDo field is set to volatile I suspect a memory issue.
But why exactly is it happening? Debugging doesn't help, once you start stepping through, everything behaves as expected.
An explanation would be appreciated.
The first problem is that you are setting the Runnable workToDo from the main thread and then reading it in the 2 forked threads without synchronization. Any time you modify a field in multiple threads, it should be marked as volatile or someone synchronized.
private volatile Runnable workToDo;
Also, because multiple threads are doing counter++ this also needs to be synchronized. I recommend an AtomicInteger for that.
private AtomicInteger counter = new AtomicInteger(0);
...
threads[counter.incrementAndGet() % 2].setWork(this);
But I think the real problem may be one of race conditions. It is possible for both threads to set the workToDo to be the Runnable and then have them both return and set it back to be null so they will just spin forever. I'm not sure how to fix that.
1. threads[0] has it's `workToDo` set to the runnable. It calls `run()`.
2. at the same time threads[1] also calls `run()`.
3. threads[0] sets the `workToDo` on itself and threads[1] to be the runnable.
4. at the same time threads[1] does the same thing.
5. threads[0] returns from the `run()` method and sets `workToDo` to be `null`.
6. threads[1] returns from the `run()` method and sets `workToDo` to be `null`.
7. They spin forever...
And, as you mention, the spin loop is crazy but I assume this is a demonstration thread program.
The problem occurs right between these lines:
workToDo.run();
workToDo = null;
Suppose the following sequence of events occurs:
- Original Runnable runs. "Ping!".setWork() called
- Ping! thread realizes workToDo != null, calls run(), the stops between those two lines
- "Pong!".setWork() called
- Pong! thread realizes workToDo != null, calls run()
- "Ping!".setWork() called
- Ping! thread resumes, sets workToDo = null, ignorantly discarding the new value
- Both threads now have workToDo = null, and the counter is frozen at 2,...,80
Program hangs
my 2 cents....
import java.util.concurrent.atomic.AtomicReference;
class WorkerThread extends Thread {
private AtomicReference<Runnable> work;
public WorkerThread(String name) {
super(name);
work = new AtomicReference<Runnable>();
}
#Override
public void run() {
while (true){
Runnable workToDo = work.getAndSet(null);
if ( workToDo != null ) {
workToDo.run();
}
}
}
public void setWork(Runnable newWork) {
this.work.set(newWork);
}
}

Categories

Resources