I know this is one of the most basic topic that even second year university should be familiar with, however, this afternoon I have spent nearly a whole afternoon to debug some issues with Java Multi-threading, and only at that point I realized I am far far away from fully understanding the seemingly easy problem.
As I have reading through all kinds of tutorials, discussions available, I believe the best way would be to sommarize what I have found and record it as my own writing.
So here is the beginning, Java always running with a single thread if there is no request for a new thread to be spawned. However, in some circumstances, a separate thread is needed to perform some other tasks either to be parallel with the main thread or as a background job. There are two ways to achieve multi-thread in Java, as everyone should be familiar with: implements Runnable and extends Thread.
Basically, most of the time, implements Runnable should be the preference over extends Thread, unless you need to specifically override the life cycle method of the thread (which is rare). These two ways do nearly the same thing except when you subclass Thread, you are trapped in the spot that no other class can inherit as Java only allows single inheritance. While if you implements the interface, you still have the ability to extend any class you wish.
Next, let's go into the main method in the body -- run(). Actually, you have the choice to call run() and start() to execute the body. However, there is some slight differences between these two methods. run() will execute the method immediately in the current thread, and start() will spawn a new thread and the execution will be invoked undeterministicallly. As a rule of thumb, we should avoid to use run() but use start() all the time. The reason we have a multi-thread class is to run it in a separate thread. If we just call the run(), everything will run sequentially as there is no thread existed. run() should always invoked by JVM not the application.
Another point we should pay some attention is Executor which comes from JDK 5. Instead of explicitly calling new MyThread().start() to invoke the new thread, Executor can decouple the task submission from the real method perform -> executor.execute(new MyThread()).
Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts
Sunday, March 6, 2011
Monday, October 4, 2010
Exception Handling Principles
1. System.out.println is expensive. These calls are synchronized for the duration of disk I/O, which
significantly slows throughput.
2. By default, stack traces are logged to the console. But browsing the console for an exception trace isn't feasible in
a production system.
3. In addition, they aren't guaranteed to show up in the production system, because system administrators can map
System.out and System.errs to ' ' [>nul] on NT and dev/nul on UNIX. Moreover, if you're running the
J2EE app server as an NT service, you won't even have a console.
4. Even if you redirect the console log to an output file, chances are that the file will be overwritten when the
production J2EE app servers are restarted.
5. Using System.out.println during testing and then removing them before production isn't an elegant solution
either, because doing so means your production code will not function the same as your test code.
significantly slows throughput.
2. By default, stack traces are logged to the console. But browsing the console for an exception trace isn't feasible in
a production system.
3. In addition, they aren't guaranteed to show up in the production system, because system administrators can map
System.out and System.errs to ' ' [>nul] on NT and dev/nul on UNIX. Moreover, if you're running the
J2EE app server as an NT service, you won't even have a console.
4. Even if you redirect the console log to an output file, chances are that the file will be overwritten when the
production J2EE app servers are restarted.
5. Using System.out.println during testing and then removing them before production isn't an elegant solution
either, because doing so means your production code will not function the same as your test code.
6. If you can't handle an exception, don't catch it.
7. Catch an exception as close as possible to its source.
8. If you catch an exception, don't swallow it.
9. Log an exception where you catch it, unless you plan to re-throw it.
10. Preserve the stack trace when you re-throw the exception by wrapping the original exception in the new one.
11. Use as many typed exceptions as you need, particularly for application exceptions. Do not just use
java.lang.Exception every time you need to declare a throws clause. By fine graining the throws clause, it is self-
documenting and becomes evident to the caller that different exceptions have to be handled.
12. If you programming application logic, use unchecked exceptions to indicate an error from which the user cannot
recover. If you are creating third party libraries to be used by other developers, use checked exceptions for
unrecoverable errors too.
13. Never throw unchecked exceptions in your methods just because it clutters the method signature. There are some
scenarios where this is good (For e.g. EJB Interface/Implementations, where unchecked exceptions alter the bean
behavior in terms of transaction commit and rollback), but otherwise this is not a good practice.
14. Throw Application Exceptions as Unchecked Exceptions and Unrecoverable System exceptions as unchecked
exceptions.
15. Structure your methods according to how fine-grained your exception handling must be.
Monday, July 12, 2010
Pipe or Redirect within Java Command
it's common knowledge to use Runtime.getRuntime().exec(command) to execute any Unix command or Windows command in a Java application. However, when you try to include the pipe '|' or redirect '>' in the command to alter any output pattern, most of the time the Java will not interpret your command as expected which will turn out to be an error finally. For example, when I tried to run ffmpeg command to encode any video and would like to capture those outputs into a log file, an error of "Unable to find a suitable output format for '>'" will appear.
In order to make Java "understand" out purpose, you cannot directly insert the usual command into the exec() parameter. There is a workaround which will solve the issue.
Construct an array:
String[] commands = {
"/bin/sh",
"-c",
YOUR REAL COMMAND HERE
}
and pass the commands as argument to the Runtime.getRuntime().exec(commands). In this way, the Java environment will make a sh (YOU COULD USE BASH) environment to execute your command, which will take the pipe and redirect into consideration.
In order to make Java "understand" out purpose, you cannot directly insert the usual command into the exec() parameter. There is a workaround which will solve the issue.
Construct an array:
String[] commands = {
"/bin/sh",
"-c",
YOUR REAL COMMAND HERE
}
and pass the commands as argument to the Runtime.getRuntime().exec(commands). In this way, the Java environment will make a sh (YOU COULD USE BASH) environment to execute your command, which will take the pipe and redirect into consideration.
Thursday, July 8, 2010
Seven Java EE Performance Problems
1) Slow-running applications
2) Applications that degrade over tim
3) Slow memory leaks that gradually degrade performance
4) Huge memory leaks that crash the application server
5) Periodic CPU spikes and application freezes
6) Applications that behave significantly differently under a heavy load under normal usage patterns
7) Problems or anomalies that occur in production but cannot be reproduced in a test environment
2) Applications that degrade over tim
3) Slow memory leaks that gradually degrade performance
4) Huge memory leaks that crash the application server
5) Periodic CPU spikes and application freezes
6) Applications that behave significantly differently under a heavy load under normal usage patterns
7) Problems or anomalies that occur in production but cannot be reproduced in a test environment
Sunday, March 14, 2010
Export a jar file in Eclipse project
If you would like to export your eclipse project into a jar file, maybe the first thing comes out of your mind is to build with Ant. But here I'd like to recommend a very handy tool called FatJar, which is a very helpful plug-in for eclipse to package your project.
Really simple, just install the plug-in from http://kurucz-grafika.de/fatjar. Then export as a fat jar will generate the jar file you need.
More details can be found in its tutorial, just Google it.
Really simple, just install the plug-in from http://kurucz-grafika.de/fatjar. Then export as a fat jar will generate the jar file you need.
More details can be found in its tutorial, just Google it.
Tuesday, March 9, 2010
A piece of Java code to split large file
Working with Azure recently, sometimes when you are trying to upload large files into the Azure storage service, you cannot simply push it. For files larger than 64MB, you have to split the file into small trunks, and upload each of them as a blob list. It's not hard to understand the concept however split large files may not seem to be easy for junior developers.
Here is a simple code to split large files into small pieces which may be helpful if tbis is what you want to achieve:
class FileSplit {
private File f;
private FileInputStream fis;
private String path;
private String fileName;
int count;
public FileSplit(File f) {
this.f = f;
fileName = f.getName();
count = 0;
path = f.getParent();
}
public int split() {
try {
log.info("Start to split files");
fis = new FileInputStream(f);
byte buf[] = new byte[4 * 1000 * 1000];
int num = 0;
while ((num = fis.read(buf)) != -1) {
if (createSplitFile(buf, 0, num) == -1) {
return 0;
}
count++;
log.info("Finished one piece");
}
log.info("All finished");
} catch (Exception e) {
log.severe(e.getMessage());
} finally {
if (fis != null) {
try {
fis.close();
} catch (Exception e) {
log.severe(e.getMessage());
}
}
}
return count;
}
private int createSplitFile(byte buf[], int zero, int num) {
FileOutputStream fosTemp = null;
try {
fosTemp = new FileOutputStream(path + "/" + count + ".tmppt");
fosTemp.write(buf, zero, num);
fosTemp.flush();
} catch (Exception e) {
return -1;
} finally {
try {
fosTemp.close();
} catch (Exception e) {
log.severe(e.getMessage());
}
}
return 1;
}
}
Here is a simple code to split large files into small pieces which may be helpful if tbis is what you want to achieve:
class FileSplit {
private File f;
private FileInputStream fis;
private String path;
private String fileName;
int count;
public FileSplit(File f) {
this.f = f;
fileName = f.getName();
count = 0;
path = f.getParent();
}
public int split() {
try {
log.info("Start to split files");
fis = new FileInputStream(f);
byte buf[] = new byte[4 * 1000 * 1000];
int num = 0;
while ((num = fis.read(buf)) != -1) {
if (createSplitFile(buf, 0, num) == -1) {
return 0;
}
count++;
log.info("Finished one piece");
}
log.info("All finished");
} catch (Exception e) {
log.severe(e.getMessage());
} finally {
if (fis != null) {
try {
fis.close();
} catch (Exception e) {
log.severe(e.getMessage());
}
}
}
return count;
}
private int createSplitFile(byte buf[], int zero, int num) {
FileOutputStream fosTemp = null;
try {
fosTemp = new FileOutputStream(path + "/" + count + ".tmppt");
fosTemp.write(buf, zero, num);
fosTemp.flush();
} catch (Exception e) {
return -1;
} finally {
try {
fosTemp.close();
} catch (Exception e) {
log.severe(e.getMessage());
}
}
return 1;
}
}
Subscribe to:
Posts (Atom)