consider this code which basically has an object(WaitedObject) and two threads(SomeTask and SomeTaskWithWait) compete to call the methods (longRunningTask() and withWaitTask() respectively) of the object synchronously
package closerLookAtWait;
class WaitedObject
{
int i=0;
synchronized void longRunningTask()
{
System.out.println(i++);
for(long j=999; j>0; j--)
{}
}
synchronized void withWaitTask()
{
System.out.println("Now Waiting");
long time1 = System.currentTimeMillis();
try {
//Thread.sleep(500);
wait(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long time2 = System.currentTimeMillis() - time1;
System.out.println("Done Waiting for "+time2);
}
}
class SomeTask implements Runnable
{
WaitedObject wo;
SomeTask(WaitedObject wo)
{
this.wo = wo;
}
#Override
public void run() {
while(true)
wo.longRunningTask();
}
}
class SomeTaskWithWait implements Runnable{
WaitedObject wo;
SomeTaskWithWait(WaitedObject wo)
{
this.wo = wo;
}
#Override
public void run() {
while(true)
wo.withWaitTask();
}
}
public class SomeWaitingWithLong {
public static void main(String[] args) {
WaitedObject wo = new WaitedObject();
new Thread(new SomeTask(wo)).start();
new Thread(new SomeTaskWithWait(wo)).start();
}
}
sample output:
well i got output as 54,54,50,65,51,52,..,78,..84,..50,52,52.
now my question is why such inaccuracy? (even 65 is ok, but why 84?)
One of the reasons is, OS puts that thread in suspended mode for the time(ms) you provide in wait(). When the time completes it isn't guarrented that your thread will be executed at once because OS has assigned another thread with a higher priority in your process to be executed by the processor or some other higher priority process is being assigned to the processor for execution. Even if your thread was at highest priority, even then there will be some delay sometimes because of context switching & in Java's case, GC.
Simple answer: Android is not a real time OS.
Related
package threadShareResource1;
public class NonSynchro1 {
private int sum = 0;
public static void main(String[] args) {
NonSynchro1 n = new NonSynchro1();
n.task();
System.out.println(n.getSum());
}
public synchronized void sumAddOne(){
sum++;
}
public void task(){
for (int i = 0; i < 100; i++) {
new Thread(new Runnable(){
#Override
public void run() {
sumAddOne();
}
}).start();
/* try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} */
}
}
public int getSum() {
return sum;
}
}
Without the commented part of code, the program has data corruption, which is not 100 every time I run it. But I thought the synchronized keyword should acquires a lock on the sumAddOne method, which is the critical region of my program, allowing one thread accessing this method every time.
I've try to use ExecutorService as well, but it doesn't give 100 all the runs.
public void task(){
ExecutorService s = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
s.execute(new Thread(new Runnable(){
#Override
public void run() {
sumAddOne();
}
}));
}
s.shutdown();
while(!s.isTerminated()){}
}
In Task(), you start 100 threads (which is a lot) and each one is to add 1 to sum.
But when Task is done all you know is that 100 threads are in some process of having started. You don't block before calling println(), so how do you know all the threads have completed?
The sleep probably "prevents the corruption" just because it gives the system time to finish launching all the threads.
Beyond that you are using Synchronized correctly. Any place multiple threads may write to the same variable you need it and, in general (simplifying), you don't need it if you are only reading.
Synchronised keyword is used correctly, the problem is that you are not waiting for the threads to finish. Here is a possible solution:
public class NonSynchro1 {
private static final ExecutorService executorService = Executors.newCachedThreadPool();
private int sum = 0;
public static void main(String[] args) {
NonSynchro1 n = new NonSynchro1();
n.task();
System.out.println(n.getSum());
executorService.shutdown();
}
public synchronized void sumAddOne() {
sum++;
}
public void task() {
List<Callable<Object>> callables = new ArrayList<>();
for (int i = 0; i < 100; i++) {
callables.add(() -> {
sumAddOne();
return null;
});
}
List<Future<Object>> futures;
try {
futures = executorService.invokeAll(callables);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
futures.forEach(future -> {
try {
future.get();
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
});
}
public int getSum() {
return sum;
}
}
First we create a list of callables - a list of functions that will be executed in parallel.
Then we invoke them on the executor service. newCachedThreadPool I have used here, by default has 0 threads, it will create as many as necessary to execute all passed callables, the threads will be killed after being idle for a minute.
Finally, in the for-each loop we resolve all futures. get() call will block until the function was executed by the executor service. It will also throw exception if it was thrown inside the function (without calling get() you would not see such exception at all).
Also, it is a good idea to shutdown the executor service when you want to terminate the program gracefully. In this case, it is just executorService.shutdown() at the end of main method. If you don't do this, the program will terminate after a minute when idle threads are killed. However, if different executor service, threads might not be killed when idle, in which case the program would never terminate.
Just for completeness sake: Here's a solution showing how the original program can be made to wait for all threads to finish by joining them:
for (Thread t : n.task())
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
which requires task to return the threads it creates. In this case we don't need to complicate things with caching managers or collections: a simple array will do. Here's the complete class:
public class TestSynchro1 {
private int sum = 0;
public synchronized void sumAddOne() {
sum++;
}
public Thread[] task(int n) {
Thread[] threads = new Thread[n];
for (int i = 0; i < n; i++) {
(threads[i] = new Thread(new Runnable() {
#Override
public void run() {
sumAddOne();
}
})).start();
}
return threads;
}
public static void main(String[] args) {
TestSynchro1 n = new TestSynchro1();
for (Thread t : n.task(100))
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(n.sum);
}
}
I have written some Java code, which will call a C interrupt handler.
In Java thread A, I use waitFor() to wait the interrupt coming and then execute reboot.
In Java thread B, I will loop printing a counter value and sleep several milliseconds.
And I hope when I detect the interrupt, and then stop the printing in thread B at once, but failed. In fact, the system detects the interrupt in time, but the printing continues for maybe 10 seconds and then reboot. Note: reboot occurs maybe 11 seconds after the interrupt(press a button), the hardware is not fast.
Below is my code, any suggestion? Thanks!
import java.io.IOException;
class ThreadTesterA implements Runnable
{
private int counter;
private String cmds[] = new String[1];
private Process pcs;
#Override
public void run()
{
cmds[0] = "./gpio-interrupt";
try {
pcs = Runtime.getRuntime().exec(cmds);
if(pcs.waitFor() != 0) {
System.out.println("error");
} else {
ThreadTesterB.setClosed(true);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ThreadTesterB implements Runnable
{
private int i;
private static boolean closed=false;
public static void setClosed(boolean closed)
{
closed = closed;
}
#Override
public void run()
{
// replace it with what you need to do
while (!closed) {
System.out.println("i = " + i);
i++;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println();
}
}
public class ThreadTester
{
public static void main(String[] args) throws InterruptedException
{
Thread t1 = new Thread(new ThreadTesterA());
Thread t2 = new Thread(new ThreadTesterB());
t1.start();
t1.setPriority(Thread.MAX_PRIORITY);
//t1.join(); // wait t1 to be finished
t2.start();
//t2.join();
}
}
You're writing and reading a boolean variable (closed) from 2 different threads without any kind of synchronization. There is thus no guarantee that what you wrote in one thread is visible in the other thread. You need to either
make the boolean variable volatile
access the boolean variable (writing and reading) using blocks or methods synchronized on the same lock
use an AtomicBoolean instead of a boolean
I would use the third solution.
In my code:
public class thread1 implements Runnable {
public static void main(String[] args) {
thread1 d = new thread1();
new Thread(d).start();
Thread t1 = new Thread(d);
t1.start();
}
#Override
public void run() {
for (int i = 0; i < 3; i++) {
sleep1();
sleep2();
}
}
void sleep1() {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
synchronized void sleep2() {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I ran my code and calculate its running time to finished.
The minimum time to finished was 7 seconds.
Why?
It should be 6 seconds, Because
3loops * 2seconds = 6seconds.
Because of context switching. sleep() is not a guaranteed amount of time, but is subject to other things going on in the system. It will try to come back, but may not succeed. Also, probably rounding in your IDE.
Program running time also accountable. You have put 6 secs to thread sleep. So Next thread will be executed. So context switching takes place.
How to pass parameter to an already running thread in java -- not in the constructor, & probably without using wait() (possible ??)
Something similar to a comment in How can I pass a parameter to a Java Thread?
Do you mean passing a parameter to an already running thread ? Because all the current answers are about passing parameters to new threads... – Valentin Rocher May 18 '09 at 10:43
[edited]
yes, I was looking for something like the producer/consumer pattern.
I wanted something like a thread in which has the processing & is ready
for keyboard input. The other thread is just to monitor network and pass
on the received text to the processing thread.
Maybe what you really need is blocking queue.When you create the thread, you pass the blocking queue in and the thread should keep checking if there is any element in the queue. Outside the thread, you can put elements to the queue while the thread is "running". Blocking queue can prevent the thread from quit if their is nothing to do.
public class Test {
public static void main(String... args) {
final BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
Thread running = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
String data = queue.take();
//handle the data
} catch (InterruptedException e) {
System.err.println("Error occurred:" + e);
}
}
}
});
running.start();
// Send data to the running thread
for (int i = 0; i < 10; i++) {
queue.offer("data " + i);
}
}
}
The "other thread" will have its own life, so you can't really communicate with it / pass parameters to it, unless it actively reads what you gives to it.
A thread which you allows you to communicate with it typically reads data from some buffered queue.
Have a look at ArrayBlockingQueue for instance, and read up on the Consumer-Producer pattern.
public class T1 implements Runnable {
//parameter of thread T1
public static AtomicBoolean flag = new AtomicBoolean();
#Override
public void run() {
}
}
public class T2 implements Runnable {
#Override
public void run() {
//parameter to an already running thread
T1.flag.set(true);
}
}
What about such way:
class TestRun implements Runnable
{
private int testInt = -1;
public void setInt(int i)
{
this.testInt = i;
}
#Override
public void run()
{
while (!isFinishing())
{
System.out.println("Working thread, int : " + testInt);
try
{
Thread.sleep(2500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
.....
TestRun first = new TestRun();
TestRun second = new TestRun();
(new Thread(first)).start();
(new Thread(second)).start();
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
}
first.setInt(101);
second.setInt(102);
I came across this blog site where the author is testing against the maximum number of threads before the machine throws a java.lang.OutOfMemoryError. However, in my below test codes, i am unable to hit the error despite the arbitrary large threads spawned.
for (int i = 0; i < 1000000; i++) {
Thread thread = new Thread(new Car());
thread.setName(Integer.toString(i));
thread.start();
}
Try sleeping inside the thread, otherwise it might end up too quickly and get garbage collected, as shown in the example code:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
while (!Thread.interrupted()) {
Thread.sleep(1000);
}
} catch (InterruptedException ignored) {
//
}
}
});
If the (Runnable) Car instance exits shortly after being started, the memory allocated for the thread is freed. If the rate of freeing memory is greater than the thread spawning rate, you'll never get an OutOfMemoryError. You can prevent that by making Car run for a long time, for example:
class Car implements Runnable {
public void run() {
Thread.sleep(10000000);
}
}
Also take a look at the same problem which is covered in the JavaSpecialists Newsletter # 149
http://www.javaspecialists.eu/archive/Issue149.html
Here is a small piece of code that you can run to find out how many inactive threads you can start on your JVM:
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
public class ThreadCreationTest {
public static void main(String[] args)
throws InterruptedException {
final AtomicInteger threads_created = new AtomicInteger(0);
while (true) {
final CountDownLatch latch = new CountDownLatch(1);
new Thread() {
{ start(); }
public void run() {
latch.countDown();
synchronized (this) {
System.out.println("threads created: " +
threads_created.incrementAndGet());
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
};
latch.await();
}
}
}