I saw a Java example that had a main method labeled as synchronized, calling another static synchronized method. The effect is that, basically, the other method runs on the separate thread only after the main method has returned.
What practical functionality would such a construct have?
public class SynchronisedMain {
public static synchronized void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
#Override
public void run() {
thingy();
}
}).start();
System.out.println("Kickstarted thingy thread.");
TimeUnit.MILLISECONDS.sleep(1000);
}
public static synchronized void thingy() {
System.out.println("Thingy!");
}
}
It's probably useful as a makeshift "application closed handler", doing some cleanup duty before the app finishes entirely. It's pretty contrived though...
There is nothing that says the main function can only be used as the entry point to a program. Being static, there is no reason other classes couldn't call SynchronisizedMain.main(). Being synchronized prevents multiple instances from being executed concurrently which might be desirable.
Related
You might think that this question is duplicate of this one but no answers of that question helps me for understanding synchronized method in android. I searched a lot on google for understanding synchronized methods and i found some answer but they didn't help me to perfectly understand Synchronized methods because no answer has any perfect practical example.
I have tried to understand synchronized method by implement 2 synchronized methods in my code and executing them concurrently but i am failed in properly implementing them. So, please provide explanation of synchronized method with simple example so, others like me also can understand it simply and in a faster way.
UPDATE
I am not sure i am going in right direction or not but i have tried following code which have 2 synchronized methods.
synchronized void add() {
counter++;
Log.e("JK", String.valueOf(counter));
}
synchronized void minus() {
counter--;
Log.e("JK", String.valueOf(counter));
}
and i have called this methods in two different threads using below code.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
synchronized (counter++) {
add();
}
}
},500);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
minus();
}
},1000);
Synchronized method is a method which can be used by only one thread at a time.
Other threads will be waiting until the method will be released.
You should have only serious reasons to declare method as synchronized because such method decreases the productivity. The classic case of synchronized method usage is when several threads are using same resources i.e. change state of some object and it is needed to make sure only one thread performs it at a time, otherwise it will cause inconsistency. Also make sure to make synchronized method as small as possible, ideally reduce it to contain only operations which can manipulate common resources.
For example the class Reporter has common resource fileWriter. It writes to file some messages with information about authors.
class Reporter{
private FileWriter fileWriter;
public synchronized void addRecord(String author, String message) throws IOException {
fileWriter.write("\n<<<<<<<<<<>>>>>>>>>>\n");
fileWriter.write("Message written by:" + author + "\n");
fileWriter.write("Message content:" + message);
}
public Reporter(FileWriter fileWriter) {
this.fileWriter = fileWriter;
}
}
Suppose you are running this code from 2 different threads:
Reporter reporter = new Reporter("path/report");
...
Thread thread = new Thread(){
public void run(){
reporter.addRecord("John", "Hi");
}
}
thread.start();
Thread thread2 = new Thread(){
public void run(){
reporter.addRecord("Bill", "Hello");
}
}
thread2.start();
The result for synchronized method will be like this :
<<<<<<<<<<>>>>>>>>>>
Message written by:John
Message content:Hi
<<<<<<<<<<>>>>>>>>>>
Message written by:Bill
Message content:Hello
If method is not synchronized several threads may write to file simultanously, which can cause an unpredictable sequence in file, like this:
<<<<<<<<<<>>>>>>>>>>
<<<<<<<<<<>>>>>>>>>>
Message written by:John
Message written by:Bill
Message content:Hello
Message content:Hi
Synchronized method is a method which can be used by only one thread at a time. Other threads will be waiting until the method will be released. You should have only valid reasons to declare method as synchronized because such method decreases the productivity and performance.
I'm using OpenGL in Java and I have to delete external resources (like vbos). The recommended way is to have a Disposable interface. However doing that would require me to have nearly every class dealing with resources implement this interface. And I've tried that but it's often not clear to me which object should be responsible for calling the dispose() method. That's why I programmed something like this:
public abstract class Destroyable {
private static final ArrayList<Runnable> cleanupTasks = new ArrayList<Runnable>();
public static void cleanup() {
synchronized (cleanupTasks) {
for (Runnable cleanupTask : cleanupTasks) {
cleanupTask.run();
}
}
}
protected abstract void destroy();
#Override
protected void finalize() throws Throwable {
try {
synchronized (cleanupTasks) {
// Let's do cleanup in the main thread as the garbage collector runs in another thread
cleanupTasks.add(new Runnable() {
public void run() {
destroy();
}
});
}
} finally {
super.finalize();
}
}
}
As the garbage collector won't run most of the time I'm calling Destroyable.cleanup() together with System.gc() every five seconds.
It's not that bad if some of the resources aren't destroyed at the end (like static ones) because I'm deleting the context at the end (which destroys the other resources as well).
Is this a good idea or is there a better way of doing this?
I'm doing a short course about Threads in Java, in one of my homeworks they asked me: ¿Why you don't should be synchronize the run method? show an example.
I searched about it, and that i think is use synchronized for a run method is not useful, at least commonly. Because the people don't call the run method manually, so the synchronized effect isn't visible creating multiple instances of a object with synchronized run.
So, i would like know if exist another reason or if i'm wrong.
Syncrhonizing the run() method of a Runnable is completely pointless unless you want to share the Runnable among multiple threads and you want to serialize the execution of those threads. Which is basically a contradiction in terms.
If the run method of a Runnable were synchronized, then either
a) you have many runnables (in which case, no need to synchronise, as each one is called on a different object), or else
b) you have one runnable being called in many threads - but then they clearly won't run in parallel -- thus defeating the purpose of having multiple threads!
You may synchronize on run method, nothing wrong with it. I think the reasons behind this advice should be explained to you by the instructor of course.
We need synchronization when there are shared resources (between threads).
Synchronizing on a method is same as synchronizing on this which will block other method calls.
As a counter example, a poor man's Future implementation;
public class SynchronizedRun {
static abstract class Future<T> implements Runnable{
private T value;
public synchronized T getValue(){
return value;
}
protected void setValue(T val){
value = val;
}
}
public static void main(String[] args) {
Future<Integer> longRunningJob = new Future<Integer> (){
#Override
synchronized public void run() {
try {
Thread.sleep(5000);
setValue(42);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(longRunningJob).start();
System.out.println("getting results");
System.out.println("result = " + longRunningJob.getValue());
}
}
This code is from Effective Java (Item 66): (without sync or volatile this never ends)
public class ThreadPractice {
static boolean canrunstatic;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}
As Bloch mentioned in that chapter it will never write "finished" to the console. I've been playing around with this class, and add that line to the runnable run method:
System.out.println("im still running");
With this the while loop doesn't only increment i but prints out this string in every loop. But what drives me crazy, that this way the thread stops after 1 sec, when main thread comes back from sleep.
modified: (stops without volatile/sync)
public class ThreadPractice {
static boolean canrunstatic;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!canrunstatic){i++;System.out.println("im still running");}
System.out.println("finished");
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
canrunstatic = true;
}
So what is the logic behind this?
Precisely, it is just not guaranteed that the thread will ever stop, but it is not forbidden that it does stop. The logic behind this is provided by the Java Memory Model, which is a rather complicated topic, but needed in order to understand Multithreading in Java.
The concept is that a write to a non-volatile field of one thread is only required to be seen by another thread if these two actions synchronize with each other. A compiler is allow to reorder some actions if the behavior exhibited by the thread it is executed in does not change. But another thread might see this. So you need proper synchronization in order to tell the compiler that reordering is not allowed in some parts.
Read the full paper about this here: JSR-133
Writing data to the console is often implemented a thread safe operation.
In that case your act of writing data to the console can also trigger updating of the canrunstatic variable as seen by your backgroundThread.
Note that this is not promised by the Java Memory Model, nor by the implementation of java System.out
I've got 2 classes (1 is a basic class, 2nd one extends Thread class) and I'm trying to access an object (class) that is initialized in my thread class on run() using setText()
public class TThread extends Thread{
Patcher pf;
public TThread(String string) {
setName(string);
start();
}
#Override
public void run() {
pf = new Patcher("Checking Serial key..."); //<=== Class initialized here in a separate thread
}
public void setText(String string) {
pf.setText(string); //<=== Trying to access patcher here, throws NullPointerException
}
}
This is how I call TThread
public void myCall(){
TThread tpf = new TThread("pf thread");
//some code later
try{
tpf.setText("blabla");
}
The pf.setText() throws NullPointerException when I'm trying to access patcher from another thread.
How can I get to that thread and access patcher from another class or this class?
This is classic race condition. Because you have two threads, there is no guarantee what will happen first. pf might be accessed by main thread before it's initialized by a background thread.
Right now, your program is unpredictable. Try adding Thread.sleep(100); at the beginning of setText method. It will appear to work correctly, but it might still fail in some specific circumstances.
One way to fix it is to wait in main thread until pf is initialized:
#Override
public synchronized void run() {
pf = new Patcher("Checking Serial key...");
notifyAll();
}
public synchronized void setText(String string) throws InterruptedException {
while(pf==null) {
wait();
}
pf.setText(string);
}
Be careful. If you have not worked with threads before, it might be tricky to get right.
It is a time consuming process to start a new Thread. With a small delay your code will execute successfully:
TThread thread = new TThread("str");
Thread.sleep(1000);
thread.setText("str2");
So the problem is that your thread had no time to execute the run method (and create the instance). You should check the existance of the instance, and wait for it's creation in the setText method - or instantiate it in the TThread's constructor.