|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
java.lang.Objectorg.vishia.java2C.test.TestThread
public class TestThread
This class demonstrates and tests the usage of threads with the synchronized access to data (mutex).
It implements the run()-Method of the Thread defined in the interface Runnable.
The threads private data which should be able to access only by the current thread are stored
in an extra class, here defined as static inner class.
| Nested Class Summary | |
|---|---|
private static class |
TestThread.TestThreadLocalData
This class is defined only to use in the threads context. |
| Field Summary | |
|---|---|
private int |
testCt1
Two test counter, they will be count always simultaneously. |
private int |
testCt2
Two test counter, they will be count always simultaneously. |
(package private) int |
testCtInterrupted
This counter is used to test whether the interrupting of the thread works. |
private TestWaitNotify.WaitNotifyData |
theNotifyingData
Aggregation to data to check wait/notify. |
(package private) java.lang.Thread |
theThread
A Thread-instance is a composite part of this class. |
private boolean |
threadFinished
This is a central thread-control variable. |
private boolean |
threadRunning
This is a central thread-control variable. |
| Constructor Summary | |
|---|---|
TestThread(TestWaitNotify.WaitNotifyData theNotifyingData)
Constructor. |
|
| Method Summary | |
|---|---|
boolean |
isThreadFinished()
Returns true if the class private variable threadFinished is set. |
void |
otherThreadRoutine()
This routine is called from outside in another thread. |
void |
run()
This is the thread main-routine complying the Java rules. |
void |
start()
Facade routine to start the Thread. |
(package private) void |
testSynchronized(TestThread.TestThreadLocalData threadLocalData)
This routine shows and support test of a mutex-access. |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
|---|
private boolean threadRunning
private boolean threadFinished
private int testCt1
synchronized
is used. The data of an instance of this class, especially this counters are visible from outside the thread.
Because there are private, an access to it is only possible in this class. But the method which is accessing
may be called from another thread. Therefore a mutex-access is necessary,
see testSynchronized(org.vishia.java2C.test.TestThread.TestThreadLocalData)
and otherThreadRoutine().
private int testCt2
synchronized
is used. The data of an instance of this class, especially this counters are visible from outside the thread.
Because there are private, an access to it is only possible in this class. But the method which is accessing
may be called from another thread. Therefore a mutex-access is necessary,
see testSynchronized(org.vishia.java2C.test.TestThread.TestThreadLocalData)
and otherThreadRoutine().
int testCtInterrupted
final java.lang.Thread theThread
TestWaitNotify.
private final TestWaitNotify.WaitNotifyData theNotifyingData
| Constructor Detail |
|---|
TestThread(TestWaitNotify.WaitNotifyData theNotifyingData)
theNotifyingData - The aggregation to data, which is used to test wait-notify.| Method Detail |
|---|
public void run()
theThread,
is called with ,,start(),,-method.
implements Runnable.run()
@ java2c=stackInstance. is written thereby. Large-size instances need
an adequate stack size. The Java-code for this code-snippet is:
...* @java2c=stackInstance. * /
TestThreadLocalData threadLocalData = new TestThreadLocalData();
The generated C-code is:
TestThread_Test__TestThreadLocalData_s threadLocalData;
...
init_ObjectJc(&(threadLocalData.base.object), sizeof(threadLocalData), 0);
ctorO_TestThread_Test__TestThreadLocalData(&(threadLocalData.base.object), _thCxt);
The thread contains a for-loop to force a determined call of testSynchronized,
and a call of notify(...) to test the wait/notify-concept with a third thread.
Than a sleep is called to delay the execution of the thread with deterministic milliseconds-time.
The Java-form is:
for(int liveCt = 0; liveCt <200; liveCt++){
testSynchronized(threadLocalData);
theNotifyingData.notify(testCt1);
try{ Thread.sleep(10); }
catch(InterruptedException exc){
testCtInterrupted +=1;
}
}//for
The catch clause is processed if the thread was woken up abnormal. The coding of this catch is prescribed in Java.
In C it is mapped too, but it isn't used yet.
for(liveCt = 0; liveCt < 200; liveCt++)
{ testSynchronized_TestThread_Test(ythis, & (threadLocalData), _thCxt);
theNotifyingDataMtbl.mtbl->notify( (theNotifyingDataMtbl.ref), ythis->testCt1, _thCxt);
TRY
{ sleep_ThreadJc(10, _thCxt);
}_TRY
CATCH(InterruptedException, exc)
{ ythis->testCtInterrupted += 1;
}
END_TRY
}
The call of theNotifyingDataMtbl.mtbl->notify(...) is executed dynamically,
because the destination instance can be an derived class of the reference type
in an enhancement of the example. To prevent effort to get the method table reference,
the Java-code contains a stack-local reference at top of the routine,
see Docu.D_SuperClassesAndInterfaces.D6_callingOverrideableMethods().
/**Use local variable to enforce only one preparation of the method table for dynamic call:
run in interface java.lang.Runnablefinal void testSynchronized(TestThread.TestThreadLocalData threadLocalData)
testCt1 and testCt2 of this class are decremented together.
The rule is: both counter should contain the same number. There are incremented
in the routine otherThreadRoutine() from another thread and decremented here
independently, but similar. The equality of both counter values are tested on entry
using an assert statement. The Java-Code is
synchronized(this)
{ assert(testCt1 == testCt2);
testCt1 -=2;
try{ Thread.sleep(5);}
catch (InterruptedException e){}
testCt2 -=2;
threadLocalData.x = testCt1;
}
The C-Code is:
synchronized_ObjectJc(& ((* (ythis)).base.RunnableJc.base.object)); {
{ ASSERT(ythis->testCt1 == ythis->testCt2);
ythis->testCt1 -= 2;
TRY
{ sleep_ThreadJc(5, _thCxt);
}_TRY
CATCH(InterruptedException, e){} END_TRY
ythis->testCt2 -= 2;
threadLocalData->x = ((float)(ythis->testCt1));
}
} endSynchronized_ObjectJc(& ((* (ythis)).base.RunnableJc.base.object));
The sleep-call is disposed here only to provoke a thread switch
during this mutex-saved operation. Without synchronized the interruption of this
statement block between the two counter-increments from the other thread accessing the counters
is likely, the synchronized is effective well able to test.
synchronized {
...guarded block
}
is well bounded with { .... }, the programmer can't forget the exit from the guard.
It is the syntax of Java. Hand written in C, the exit of the guard block (critical section)
may be missed because the programmer has forgotten it. The C-translation of Java is safety respectively this problem,
though an extra routine endSynchronized_ObjectJc is called.
threadLocalData - public void start()
/ **@java2c=stackSize(TestThreadLocalData+2000). * /
theThread.start();
The stackSize is necessary for the C-implementation. Because an instance of TestThreadLocalData
is created in the run()-Method, its size should be regarded.
The rest, 2000 Bytes, is a proper value for typical stack usages.
start_ThreadJc(& (ythis->theThread)
, sizeof(TestThread_Test__TestThreadLocalData_s)+2000, _thCxt);
The stackSize-annotation is translated to the stackSize-parameter-value for the start_ThreadJc-routine.
The really size should be tested at C-level-debugging.
public void otherThreadRoutine()
synchronized adequate to run().
This routine works with 500 loops in a time of 10 ms. At its end #shouldRun is set to false,
which causes an aborting of the run()-routine and therefore the finishing of the thread.
public final boolean isThreadFinished()
threadFinished is set. That occurs at last action
of the run()-routine of the thread.
|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||