I'm developing the transformer for Java 6*1) that performs a kind of partial evaluation but let's consider, for simplicity, abstract-syntax-tree interpretation of a Java program.
How to simulate the Thread
's behavior by an interpreted program?
At the moment I have in mind the following:
AstInterpreter should implement java.lang.Runnable
. It also should rewrite every new-instance-expression of the java.lang.Thread
(or its sub-class) replacing the Thread
's target (java.lang.Runnable
) with the new AstInterpreter instance:
EDIT: more complex examples provided.
EDIT 2: remark 1.
Target program:
class PrintDemo {
public void printCount(){
try {
for(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd){
threadName = name;
PD = pd;
}
public void run() {
synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start ()
{
System.out.println("Starting " + threadName );
if (t == null)
{
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch( Exception e) {
System.out.println("Interrupted");
}
}
}
program 1 (ThreadTest - bytecode interpreted):
new Thread( new Runnable() {
public void run(){
ThreadTest.main(new String[0]);
}
});
program 2 (ThreadTest - AST interpreted):
final com.sun.source.tree.Tree tree = parse("ThreadTest.java");
new Thread( new AstInterpreter() {
public void run(){
interpret( tree );
}
public void interpret(com.sun.source.tree.Tree javaExpression){
//...
}
});
Does the resulting program 2 simulate the Thread's behavior of the initial program 1 correctly?
1) Currently, source=8 / target=8
scheme is accepted.
The easiest way to create a thread is to create a class that implements the Runnable interface. Thread t1 = new Thread(new MyClass ()); t1. start();
You can create threads by implementing the runnable interface and overriding the run() method. Then, you can create a thread object and call the start() method. Thread Class: The Thread class provides constructors and methods for creating and operating on threads.
Use of yield method: Once a thread has executed the yield method and there are many threads with the same priority is waiting for the processor, then we can't specify which thread will get the execution chance first. The thread which executes the yield method will enter in the Runnable state from Running state.
I see two options:
Option 1: JVM threads. Every time the interpreted program calls Thread.start you also call Thread.start and start another thread with another interpreter. This is simple, saves you from having to implement locks and other things, but you get less control.
Option 2: simulated threads. Similar to how multitasking is implemented on uniprocessors - using time slicing. You have to implement locks and sleeps in the interpreter, and track the simulated threads to know which threads are ready to run, which have finished, which are blocked, etc.
You can execute instructions of one thread until it blocks or some time elapses or some instruction count is reached, and then find another thread which may run now and switch to running that thread. In the context of operating systems this is called process scheduling - you may want to study this topic for inspiration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With