I would like to compare thread performance on solaris/linux/windows 64 bit JVM's, with the below code.
I personally, prefer this style of coding for threading, because you have a method performing some computation and you would like to run that computation on separate thread. It does not look intuitive for me launch an object using Thread class. So, Please suggest me for alternate code style, on same lines(if required).
public class Dummy2 {
private static int NUM_OF_THREADS=100000;
public void loopSomeTime() {
Thread t = new Thread(new Runnable(){
public void run(){
int count = 0;
for(int i = 0; i < 1000000; ++i){
count++;
}
System.out.println(count);
}
});
t.start();
}
public static void main(String[] args){
long beginTime = System.nanoTime();
for(int i =0; i < NUM_OF_THREADS ; i++){
Dummy2 d = new Dummy2();
d.loopSomeTime();
}
//I need to wait here
long endTime = System.nanoTime() - beginTime;
System.out.println(endTime/(1000*1000) + "milliseconds");
}
}
How do i wait for all threads to complete before the computation of endTime in MainThread?
Note: I am java beginner and learning Java threads
The key here is you need some way to wait for all of the threads to complete. However, threads are low-level constructs that are a pain to manage correctly.
Using higher-level constructs, you can push some of the tricky dirty work into the Java framework and focus on what you are trying to do: waiting for the threads to complete.
Here is some Java that illustrates the overall design I recommend. It is not complete, but should be a good start.
public static void main(String[] args) {
final int threads = 1000;
ExecutorService exec = Executors.newFixedThreadPool(threads);
List<Future<?>> futures = new LinkedList<>();
final long start = System.currentTimeMillis();
for (int i = 0; i < threads; ++i) {
futures.add(exec.submit(makeTask()));
}
while (!futures.isEmpty()) {
Iterator<Future<?>> it = futures.iterator();
while (it.hasNext()) {
if (it.next().isDone()) {
it.remove();
}
}
}
final long duration = System.currentTimeMillis() - start;
// TODO: report the difference.
}
private static Runnable makeTask() {
// TODO: return a Runnable that does stuff.
return null;
}
You need to keep track of all of the threads and call join on each one.
public class Test {
private static int NUM_OF_THREADS = 100000;
// Keep track of my thread.
private Thread thread;
public void loopSomeTime() {
thread = new Thread(new Runnable() {
public void run() {
int count = 0;
for (int i = 0; i < 1000000; ++i) {
count++;
}
System.out.println(count);
}
});
thread.start();
}
public void waitToFinish() throws InterruptedException {
thread.join();
}
public static void main(String[] args) throws InterruptedException {
List<Test> loopers = new ArrayList<>();
long beginTime = System.nanoTime();
for (int i = 0; i < NUM_OF_THREADS; i++) {
Test d = new Test();
d.loopSomeTime();
// Keep track of all loopers.
loopers.add(d);
}
//I need to wait here
for (Test t : loopers) {
t.waitToFinish();
}
long endTime = System.nanoTime() - beginTime;
System.out.println(endTime / (1000 * 1000) + "milliseconds");
}
}
Related
I'm learning to use threads in java, since I want to speed up a task to reduce time. I try to see how long it takes to finish the threads but since I don't know how to use join in this case:
public class MyThread1 extends Thread {
int inicio;
int fin;
public MyThread1(int _inicio, int _fin) {
this.inicio = _inicio;
this.fin = _fin;
}
#Override
public void run() {
String pass;
for(int i = inicio; i < fin; i++){
pass = Integer.toString(i);
System.out.println(pass);
}
}
}
public static void main(String arg[]) throws UnknownHostException {
long previousTime;
previousTime = System.currentTimeMillis();
int threads = 10; // Number of threads
for (int i = 0; i < threads; i++) {
MyThread1 object = new MyThread1(0,10);
object.start();
}
long currentTime = System.currentTimeMillis();
double elapsedTime = (currentTime - previousTime) / 1000.0;
System.out.println("Time in seconds : " + String.valueOf(elapsedTime));
}
Add MyThread1 object to an array that is declared before the loop. After the loop, have another loop which will join on all objects.
for (int i = 0; i < threads; i++) {
MyThread1 object = new MyThread1(0,10);
arr[i] = object;
object.start();
}
for (int i = 0; i < threads; i++) {
arr[i].join();
}
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 300;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
Why the output is "n is: 300"? n isn't explicitly synchronized. And if I uncomment "Thread.sleep", the output is "n is: 299 or less".
I changed your code this way:
private static final int NTHREADS = 300;
private static AtomicInteger n = new AtomicInteger();
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
n.incrementAndGet();
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
You have to deal with racing-conditions. All the 300 threads are modifying n concurrently. For example: if two threads would have read and increment n concurrently than both increment n to the same value.
That was the reason why n wasn't always 300, you lost one increment in such a situation. And this situation could have occurred zero or many times.
I changed n from int to AtomicInteger which is thread safe. Now everything works as expected.
You better use AtomicInteger.
This question will help you with description and example: Practical uses for AtomicInteger
Static context need to have lock on the class and not on the Object. If you need a static variable to be synchronized and do not need it to be cached inside the thread locally you need to declare it as volatile.
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 30;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 1000; j++) // run a long time duration
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
output "n is: 29953"
I think the reason is, the threads run a short time duration, and the jvm don't make a context switch.
Java static field will be synchronized among threads?
No. You should make it volatile or synchronize all access to it, depending on your usage patterns.
I've made a class that counts words in given files within the same directory. Seeing as the files are very large, I've decided to achieve the count of multiple files using multiple threads.
When running the DriverClass as specified below, it get's stuck at thread one.
What am I doing wrong? As I'm iterating over queue.take(), one would expect the parser to wait for something to retrieve and move on. Getting stuck at thread 1 makes me suspect an error when putting() into the queue.
Thank's, in advance!
DriverClass:
public class WordCountTest {
public static void main(String[] args){
if (args.length<1){
System.out.println("Please specify, atleast, one file");
}
BlockingQueue<Integer> threadQueue = new LinkedBlockingQueue<>();
Runnable r;
Thread t;
for (int i = 0; i<args.length; i++){
r = new WordCount(args[i], threadQueue);
t = new Thread(r);
t.start();
int total = 0;
for (int k = 0; k<args.length; k++){
try {
total += threadQueue.take();
} catch (InterruptedException e){
}
}
System.out.println("Total wordcount: " + total);
}
}
}
WordCountClass:
public class WordCount implements Runnable {
private int myId = 0;
private String _file;
private BlockingQueue<Integer> _queue;
private static int id = 0;
public WordCount(String file, BlockingQueue<Integer> queue){
_queue = queue;
_file = file;
myId = ++id;
}
#Override
public void run() {
System.out.println("Thread " + myId + " running");
try {
_queue.put(countWord(_file));
} catch (InterruptedException e){
}
}
public int countWord(String file){
int count = 0;
try {
Scanner in = new Scanner(new FileReader(file));
while (in.hasNext()){
count++;
in.next();
}
} catch (IOException e){
System.out.println("File," + file + ",not found");
}
return count;
}
}
The problem is that you're using a nested loop, when you should be using two separate loops: one to start the WordCounts, another to collect the results, something like
public class WordCountTest {
public static void main(String[] args){
Queue<Integer> threadQueue = new ConcurrentLinkedQueue<>();
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
CountDownLatch latch = new CountDownLatch(args.length);
for (int i = 0; i<args.length; i++){
CompletableFuture.runAsync(new WordCount(args[i], threadQueue), executor)
.thenRunAsync(latch.countDown(), executor);
}
latch.await();
int sum = 0;
for(Integer i : threadQueue) {
sum += i;
}
}
}
Or however you want to implement it, the point being that you shouldn't start collecting results until all of the WordCounts have started.
You are waiting for all the results after the first thread is started. Perhaps you intended to wait for the results after all the threads have started.
Note: if you create more threads than you have CPUs its likely to be slower. I suggest using a fixed thread pool instead.
I cannot reach the last line in my code even though I used synchronized.
However, if I add something between the loop, it worked well.
public static void main(String[] args) {
int test_time = 5;
for (int i = 0; i < 100000; i++) {
//warm up
}
long t = 0;
t = System.currentTimeMillis();
byte[] b = new byte[0];
for (int i = 0; i < test_time; i++) {
new Thread(new Runnable() {
#Override
public void run() {
String i = getUserInf(); //get something from web
synchronized (b) {
++times;
System.out.println(times);
}
}
}).start();
}
while (times != test_time){
// System.out.println(String.format("times=%s,test_time=%s", times,test_time));
// if i added this line, it worked well
}
System.out.println("time:" + (System.currentTimeMillis() - t));
}
You need to declare your variable times as volatile int. Because when it's read in the while loop from the main thread, it is not guarded by b. The call to System.out.println is synchronized, so the value of times gets updated and becomes visible.
I'm writing a demo program to explain how to regulate the concurrency of a crowd of threads in Java, but the result is not as I expected. This is the code:
package parcountSyncStat;
public class Parcount extends Thread {
private static int N=1000;
private static Integer x=0;
public static void main(String[] args) throws InterruptedException {
Thread[] t = new Thread[N];
int i;
for (i = N-1; i >= 0; i--) {
t[i]=new Parcount();
t[i].start();
}
for ( i=N-1; i>=0; i-- ) t[i].join();
System.out.println(x);
}
public void run() { synchronized(x) { x++; } }
}
In a nutshell, 1000 threads try to increment the same integer x. To preserve consistency, I encacsulate the increment in a synchronized block. The parent thread waits for all processes to finish, and then prints the final value of x, which should be 1000. But it isn't. My question is: why? I'm I wrong somewhere?
Note that I obtain the expected result by implementing a class that encapsulates the integer with a synchronized "Increment" method. But replacing the synchronized with a lock/unlock pair does not work either. I'm using Eclipse and did try both openjdk and oracle jdk, with similar results.
Thanks
x++ creates a new Integer object - so every time you run that statement the lock used becomes different. If you want one single lock for all you thread, create an ad hoc object:
private static final Object lock = new Object();
and synchronize on that lock.
Thanks to assylias: here is the complete code:
public class Parcount extends Thread {
private static int N=1000;
private static Integer x=0;
private static final Object lock = new Object();
public static void main(String[] args)
throws InterruptedException {
Thread[] t = new Thread[N];
int i;
for ( i=N-1; i>=0; i-- ) {
t[i]=new Parcount();
t[i].start();
}
for ( i=N-1; i>=0; i-- ) t[i].join();
System.out.println(x);
}
public void run() { synchronized(lock) { x++; } }
}
The following code uses the owner of your shared resource x, the class Example, as the instance to synchronize with. You may try changing your code like this:
public class Example extends Thread {
public static void main(String[] args) throws InterruptedException {
Thread[] t = new Thread[N];
for (int i = N - 1; i >= 0; i--) {
t[i] = new Example();
t[i].start();
}
for (int i = N - 1; i >= 0; i--) t[i].join();
System.out.println(x);
}
private static int N = 1000;
private static int x = 0;
#Override public void run() {
synchronized (Example.class) { x++; }
}
}