Would the following Java code be thread-safe, or does it suffer from possible visibility/safe publication problems?
import java.util.ArrayList;
import java.util.List;
public class WouldThisBeSafe {
public static void main(String[] args) throws InterruptedException {
final List<String> result = new ArrayList<>();
Runnable job = new Runnable() {
#Override
public void run() {
result.add("Hello");
result.add(" ");
result.add("world!");
}
};
Thread t = new Thread(job);
t.start();
t.join();
System.out.println("result = " + result);
}
}
In my real application I have a semi-long running task that needs to load data from a server using multiple remote method calls and must run in the foreground blocking the UI, while reporting progress in a dialog. For this I am using Eclipse/JFace's ProgressMonitorDialog together with an anonymous IRunnableWithProgress instead of Runnable to report the progress. The progress monitor runs the task in a background thread (fork) and shows the progress dialog until the thread is done.
Of course my real question would be whether my actual code with ProgressMonitorDialog and an anonymous IRunnableWithProgress inner class is thread safe, but I suspect that it is equivalent to the simplified example above.
Since you call
t.join();
immediately after
t.start();
the code is perfectly thread-safe. The only issue could have been if you created multiple threads that access result, or if you had tried to print result before joining.
Related
I created my own thread class implementing the Runnable interface. But every time I start running my own thread class as a new thread, the main class thread does not terminate anymore by itself. Is this just an issue within Eclipse or would I also have problem running this on a Server? Do I have to change something calling the thread so that the main method can terminate properly?
Here's my basic self-made thread:
public class OwnThread implements Runnable {
#Override
public void run() {
//do something
}
}
Here's the main class that won't terminate anymore:
public static void main(String[] args) {
Thread thread = new Thread(new OwnThread());
thread.start();
}
When I debug it, the last called method is the exit()-method of the Thread-class. After going through these lines of code, the process goes on forever:
/**
* This method is called by the system to give a Thread
* a chance to clean up before it actually exits.
*/
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
/* Aggressively null out all reference fields: see bug 4006245 */
target = null;
/* Speed the release of some of these resources */
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
Here's a screenshot of the thread that is running forever. The TestInterface class is where the main-method is located:
But every time I start running my own thread class as a new thread, the main class thread does not terminate anymore by itself.
This is somewhat wrong. Your program does not terminate because there exists at least one non-daemon thread that still is running. The rule is: A Java program is terminated if all non-daemon threads are terminated.
I modified your program to make this behavior clear:
public class OwnThread implements Runnable {
#Override
public void run() {
runForever();
}
public static void main(String[] args) {
Thread thread = new Thread(new OwnThread());
thread.start();
runForever();
}
private static void runForever() {
while (true) {}
}
}
Running that will create two threads that will run forever. One is the main thread which is started by running the program, and the other is the thread started inside the main method:
Modifying the above code by removing the call to runForever in the main method ...
public static void main(String[] args) {
Thread thread = new Thread(new OwnThread());
thread.start();
}
... will result in a different thread picture:
Here the main thread is gone because it is terminated. But the other started thread is still running.
Side note: Suddenly another thread appears - DestroyJavaVM. Have a look at the post DestroyJavaVM thread ALWAYS running for more information.
The issue is indeed not caused by the multithreading logic itself, it is caused by Eclipse and the respective JVM. Running the exact same code in Netbeans or on an Tomcat 8 Server did not lead to any problems. A reinstallation of Eclipse did not solve the malfunction within the Eclipse framework, but having the certainty that the issue does not cause any trouble on a server is sufficient for me to close the case.
Thanks to Seelenvirtuose for the hints and his effort.
I have this issue I have no idea how to resolve and I'm at the brink of insanity. Programming, eh? :/
Anyway, I have a server which has a thread to send users all the info it needs to (which needs to run constantly) and another thread that awaits new server connections. My problem is once socket.accept() is called, the other thread doesn't execute.
So, to explain with code:
class Thread1 extends Thread {
public void run() {
while(true)
{
s=socket.accept();
}
}
class Thread2 extends Thread {
public void run() {
//do stuff
System.out.println("spam");
}
}
public static void main(String[] args)
{
Thread1 t1 = new Thread1();
t1.start();
t1.Thread2 t2 = t1.new Thread2();
t2.start();
}
}
Assume all other required member variables are present, no compile errors and connection functionality works fine. Just 'Thread2' executes only once.
So my question is, how do I resolve this problem?
Thanks in advance,
Tim.
I think you have a basic misunderstanding of threads. Let's see if we can clear that up.
Threads are simply another pipeline of execution. Think of them like tasks with a particular set of instructions. Once the task is done, the thread returns. Pretty simple idea, right?
In your example, Thread1 has an endless loop, which makes sense that it does run infinitely and does accept clients indefinitely.
However, Thread2 simply outputs some text and returns. There's nothing telling it to 'keep spinning'.
Within your main(), even though Thread2 is an inner class of Thread1 (which is kind of bad form to begin with, might I add) it doesn't actually force the thread to keep running.
You'll probably want to add a Queue to your server class that holds new sockets, and have Thread2 loop and check for entries.
Further Reading
Firstly, take a look at the Thread class. Its constructor takes a Runnable, so that's all you should be implementing when working with threads (i.e. class Foo implements Runnable and then new Thread(new Foo())).
If sockets are your fancy, perhaps some further reading on socket-server architecture and even about protocol design would be something you'd benefit from.
Some suggestions
never extend a Thread as it's a good way to confuse yourself. Never nest a Thread inside another Thread unless you really like confusion.
if you want to run a thread for each socket, then create a new thread for each socket in the loop.
Try the following (Note: You can add IOException handling code)
class SocketAcceptor implements Runnable {
public void run() {
while(true) {
Socket s=socket.accept();
SocketHandler sh = new SocketHandler(s);
new Thread(sh).start();
}
}
}
class SocketHandler implements Runnable {
final Socket s;
SocketHandler(Socket s) { this.s = s; }
public void run() {
System.out.println("New connection " + s);
s.close();
}
}
A better solution would be to use a Thread pool. e.g. An ExecutorService, but I would get this working first.
I'm using ListenableFuture from Guava, and one nice thing about them is that one pass Executor to the Futures.addCallback method, that is, ask to execute the callback on a given thread/executor.
In my Android application, I want to be able to start the asynchronous execution based on ListenableFuture in the UI thread, and schedule a callback which is also executed also on the UI thread. Therefore, I'd like to somehow submit the UI thread executor to the Futures.addCallback method mentioned above. How to achieve that?
Or, in other words, I want to have an executor for the UI thread. Is it available already in Android, or, if I have to create my own, how do I do that?
EDIT: As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?
I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.
I think I've see some implementation doing that. The basic Idea is roughly
class UiThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
#Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
You can delegate to run anything in the main thread by passing it to a handler for the main thread.
Edit: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/android/MainThreadExecutor.java for example
Edit2: You can configure the handler like e.g. SensorManager#registerListener(..., Handler handler) allows you to do.
class HandlerThreadExecutor implements Executor {
private final Handler mHandler;
public HandlerThreadExecutor(Handler optionalHandler) {
mHandler = optionalHandler != null ? optionalHandler : new Handler(Looper.getMainLooper());
}
#Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
The advantage over using the current thread's looper is that it makes it explicit which Looper you use. In your solution you take the Looper of whatever thread calls new ExecuteOnCaller() - and that's often not the thread you run code in later.
I would be happy to know how to achieve the same effect without resorting to the Android-specific stuff like Handler and Looper, just with pure Java.
Looper, Handler and the message queue behind all that logic are made of mostly pure Java. The problem with a generic solution is that you can't "inject" code to run into a thread. The thread must periodically check some kind of task queue to see if there is something to run.
If you write code like
new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("Hello");
}
}
}).start();
Then there is no way to make that thread do anything else but constantly print "Hello". If you could do that it would be like dynamically inserting a jump to other code into the program code. That would IMO be a terrible idea.
final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
new Thread(new Runnable() {
#Override
public void run() {
try {
while (true) {
Runnable codeToRunInThisThread = queue.take();
codeToRunInThisThread.run();
}
} catch (InterruptedException ignored) {}
}
}).start();
On the other hand is a simple thread that loops forever on a queue. The thread could do other tasks in between but you have to add a manual check into the code.
And you can send it tasks via
queue.put(new Runnable() {
#Override
public void run() {
System.out.println("Hello!");
}
});
There is no special handler defined here but that's the core of what Handler & Looper do in Android. Handler in Android allows you to define a callback for a Message instead of just a Runnable.
Executors.newCachedThreadPool() and similar do roughly the same thing. There are just multiple threads waiting on code in a single queue.
As an extension to this question, is it possible to do same thing, but not just with UI thread, but with any particular thread, where the call to async method is made?
The generic answer is No. Only if there is a way to inject code to run in that thread.
Based on asnwer from #zapl, here is my implementation, which also answers the edited (extended) question: https://gist.github.com/RomanIakovlev/8540439
Figured out I'll also put it here, in case if link will rot some day:
package com.example.concurrent;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;
/**
* When the calling thread has a Looper installed (like the UI thread), an instance of ExecuteOnCaller will submit
* Runnables into the caller thread. Otherwise it will submit the Runnables to the UI thread.
*/
public class ExecuteOnCaller implements Executor {
private static ThreadLocal<Handler> threadLocalHandler = new ThreadLocal<Handler>() {
#Override
protected Handler initialValue() {
Looper looper = Looper.myLooper();
if (looper == null)
looper = Looper.getMainLooper();
return new Handler(looper);
}
};
private final Handler handler = threadLocalHandler.get();
#Override
public void execute(Runnable command) {
handler.post(command);
}
}
My pattern to use it would be like this:
/**
* in SomeActivity.java or SomeFragment.java
*/
Futures.addCallback(myModel.asyncOperation(param), new FutureCallback<Void>() {
#Override
public void onSuccess(Void aVoid) {
// handle success
}
#Override
public void onFailure(Throwable throwable) {
// handle exception
}
}, new ExecuteOnCaller());
Use com.google.android.gms.tasks.TaskExecutors.MAIN_THREAD.
An Executor that uses the main application thread.
Source: Android docs
The tasks APIs are part of Google Play services since version 9.0.0.
For Android UI thread executor use:
ContextCompat.getMainExecutor(context)
To address your question and extended question to create an Executor that simply runs on the current thread and avoids Android classes:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
See documentation: https://developer.android.com/reference/java/util/concurrent/Executor
Using Guava's EventBus, I want to be able to post from a background thread (called "background") to a specific thread (in this case, thread "main") that updates the UI. I thought the following would work, but this calls the subscriber code from the background thread:
package com.example;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.common.util.concurrent.MoreExecutors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EventBusTester {
private static final Logger log = LoggerFactory.getLogger(EventBusTester.class);
public static void main(String... args) {
new EventBusTester().run();
}
private void run() {
log.info("Starting on thread {}.", Thread.currentThread().getName());
final EventBus eventBus = new AsyncEventBus(MoreExecutors.sameThreadExecutor());
eventBus.register(this);
Thread background = new Thread(new Runnable() {
#Override
public void run() {
long now = System.currentTimeMillis();
eventBus.post(now);
log.info("Posted {} to UI on thread {}.", now, Thread.currentThread().getName());
}
}, "background");
background.start();
}
#Subscribe
public void updateUi(Long timestamp) {
log.info("Received {} on UI on thread {}.", timestamp, Thread.currentThread().getName());
}
}
This prints the following:
02:20:43.519 [main] INFO com.example.EventBusTester - Starting on thread main.
02:20:43.680 [background] INFO com.example.EventBusTester - Received 1387848043678 on UI on thread background.
02:20:43.680 [background] INFO com.example.EventBusTester - Posted 1387848043678 to UI on thread background.
So my questions are:
Is it possible to do what I want, e.g. with an ExecutorService I've somehow missed, or writing a custom ExecutorService, or
Do I need some other library to accomplish this? E.g. Square's Otto (because I'll be using this on Android as well).
I'd rather stay with pure Guava, though.
Thanks!
If you use an EventBus instance then the #Subscribe method will be executed on the same thread that posted the event.
If you want to do something different then use an AsyncEventBus where you can provide an Executor to define the exact behavior in case of an event gets posted.
For instance, on Android to make every #Subscribe method run on the main thread you can do the following:
EventBus eventBus = new AsyncEventBus(new Executor() {
private Handler mHandler;
#Override
public void execute(Runnable command) {
if (mHandler == null) {
mHandler = new Handler(Looper.getMainLooper());
}
mHandler.post(command);
}
});
The Looper.getMainLooper() returns the application's main looper, which lives on the main thread of the application.
In UI applications, there is a thread running an event dispatch loop. which is processing user input events and calling handlers. Typically, UI framework provides some way to execute your code in this thread, like SwingUtilities.invokeLater(Runnable)
AsyncEventBus allows you to pass pass Executor, which will be calling UI-framework specific function for that.
There are a few questions here related to executing UI code from a worker thread on android.
I have a small image processing application which does multiple things at once using SwingWorker. However, if I run the following code (oversimplified excerpt), it just hangs on JDK 7 b70 (windows) but works in 6u16. It starts a new worker within another worker and waits for its result (the real app runs multiple sub-workers and waits for all this way). Did I use some wrong patterns here (as mostly there is 3-5 workers in the swingworker-pool, which has limit of 10 I think)?
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class Swing {
static SwingWorker<String, Void> getWorker2() {
return new SwingWorker<String, Void>() {
#Override
protected String doInBackground() throws Exception {
return "Hello World";
}
};
}
static void runWorker() {
SwingWorker<String, Void> worker
= new SwingWorker<String, Void>() {
#Override
protected String doInBackground() throws Exception {
SwingWorker<String, Void> sw2 = getWorker2();
sw2.execute();
return sw2.get();
}
};
worker.execute();
try {
System.out.println(worker.get());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
runWorker();
}
});
}
}
As nobody has fired off the link yet, it seems this is actually a known bug:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6880336
Surprisingly there are less than 100 votes for what should be a showstopper bug for most non-trivial applications.
Your SwingWorkers are executed in your SwingWorker Thread. So when you see
It seems it hangs on sw2.get() and there is only one swingworker- named thread in jdk7. On jdk6, I see 3-5 at once. – kd304
This is because the SwingWorker class is not a thread, but a task to be run on a thread, and the default configuration for the ExecutorService for SwingWorker in Java 6 is configured different from the one in Java 7. IE your SwingWorkerExecutorService (which is defined inside the SwingWorker class) has a different value for the max number of Threads to allocate to the tasks.
//From Java 6 SwingWorker
private static final int MAX_WORKER_THREADS = 10;
public final void execute() {
getWorkersExecutorService().execute(this);
}
private static synchronized ExecutorService getWorkersExecutorService() {
...
private static synchronized ExecutorService getWorkersExecutorService() {
new ThreadPoolExecutor(0, MAX_WORKER_THREADS,
1L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory)
}
You only have the one thread running the SwingWorker tasks, and that first task is waiting for the completion of the second task, which can't be run, because the Thread the second task would be run on is waiting for the second task to complete before it will return. Making on swingworker thread dependent on the execution of another is a sure path to deadlock. You may want to look at using an ExecutorService to schedule events to be run on the SwingWorker Thread, and don't make one scheduled event dependent on another scheduled event's completion.
Java 7 SwingWorker
Looking at the source code for SwingWorker, it looks like an ExecutorService is being used as a pool of worker threads. It's possible that the type of ExecutorService used has changed between Java 6 and Java 7. It looks like your code will deadlock if the ExecutorService only manages exactly 1 thread at a time (as you seem to have noticed).
This is because your 'sw2.get()' call will block the current thread, which is the same thread the sw2 will try to use. sw2 can never execute because the first worker is blocking.
I think the best solution is to change your logic so that you don't call chains of Swing workers like this.
Before JDK update 18 you could run:
public static void main(String[] args) {
new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
System.out.println("ok");
return null;
}
}.execute();
}
This code doesn't work anymore, simply because SwingWorkers must be executed on EDT.
Therefore, you can't nest SwingWorkers (sw2 will never run in you sample code in newer JDKs).
I guess replacing nested swingWorkers with executorService java.util.concurrent.Future calls is a good workaround.