Creating threads in processing

edited April 2015 in Library Questions

i am trying to understand the implementation of threads. In the code below hi from thread never appears in the console. Can someone correct my code.

  int Val1;
    MyThread thread;
    void setup()
{
  thread =new MyThread();
  size(400,400);
  thread.start();
}

void draw()
{
  Val1= mouseX;
  println(Val1);
}

 public class MyThread extends Thread
 {

   public void start()
   {
     super.start();
   }
   public void run()
   {
      println("hi from thread");
   }
 }

Answers

  • Answer ✓

    It shows up here! Just stop the sketch soon and scroll all the way up! :-\"

  • Yup. I see it too.

    Also, you don't need to override the start() method if you're just going to call super.start() from it anyway.

  • edited March 2015

    Thanks @GoToLoop & @KevinWorkman. So i understood the threads good enough. Now the next thing i want to do is i want to pass the value of mouseX to my thread and print the value using the thread. Please help me make suitable amendments to the code for achieving this.

  • edited March 2015

    Your MyThread is a sketch's inner class. Thus all of Processing's API, including mouseX, is accessible in it!

  • edited March 2015

    I made some amendments in the code. I want " hi from the main" to be printe after every Isec and this is happening. but i also want that the thread keeps on printing the value of mouseX continuously.But so far thats not happening the thread just runs for once and gives a zero value of mouseX. What amendment is required to make it continuously update the mouseX on the console while the task of printing " hi from the main" is also going on.

      int Val1;
            MyThread thread;
            void setup()
        {
          thread =new MyThread();
          size(400,400);
    
          thread.start();
        }
    
        void draw()
        {
    
    
           println("hi from the main");
           delay(1000);
        }
    
         public class MyThread extends Thread
         {
    
           public void start()
           {
             super.start();
    
           }
           public void run()
           {
             Val1= mouseX;
             print("value of mouseX is ");
              println(Val1);
           }
         }
    

    Output of above code looks like below console

  • edited March 2015 Answer ✓
    • Thread's method start() merely invokes run() in its own execution thread.
    • Once run() finishes, it's over and can't even be restarted!
    • Therefore if we wanna keep the Thread alive, we can't allow run() to end.
    • In order to accomplish that, just wrap the execution block within run() in some "infinite" loop.
    • Examples would be: while (true) {} & for ( ;; ) {}.
    • And since all your MyThread class does is executing run(), we can use something simpler.
    • Processing comes w/ a method called thread(""). Which calls some function in its own Thread.


    // forum.processing.org/two/discussion/9707/
    // creating-threads-in-processing
    
    void setup() {
      size(400, 400, JAVA2D);
      frameRate(2);
      thread("myThread");
    }
    
    void draw() {
      background((color) random(#000000));
    }
    
    void myThread() {
      for (;; delay(1000))  print(mouseX + "\t");
    }
    
  • great explanation @GoToLoop . I am aware of the quick way to execute thread using thread("") method. Is there any difference in the efficiency or performance while using the inbuilt method vs extending our own thread class. Actually i am just building my understanding to finally make a code that runs a openCV face tracking in one thread and recording values in a .csv file in another one. Also there is another way of execution using runnable it would be great if you can have some quick commnts on that too.

  • Answer ✓

    Is there any difference in the efficiency or performance while using the inbuilt method vs extending our own Thread class?

    AFAIK none! Method thread("") also instantiates a Thread for the invoked method name! :-\"
    In short, we don't need a whole class in order to have a simple method running in its own Thread.

    Also there is another way of execution using Runnable.

    Interface Runnable is the base for class Thread and others and demands run() being implemented:
    https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html

    Since Java only allows 1 extends per class, Runnable is useful for saving our 1-allowed inheritance!

  • edited March 2015

    @GoToLoop This is in context with the threads. In situations when the function to be run has thread has no arguments everything is fine. But today i tried a thread with arguments by writing thread("arbitararyfunc(boolean state)")

    i wrote the function as above in the setup. Then where i wrote the function, within the function i made an indefinite loop so that the thread stays alive. but the program says There is no public arbitararyfunc(boolean state) method in the class. How should i tackle this situation

  • edited March 2015
    • Function thread("") is just a quickly convenient way to achieve threading.
    • For anything more complex, like passing arguments &/or having states, make a formal class!
    • We can replace parameters w/ "global" variables though! ;)
  • Hey look at the code below. Let me quickly explain it so that you dont have to spend time understanding it. the SerialEvent() function gathers the serial data (this happens in a seperate thread nd serial library takes care of all the complexities) when all the bits are received it makes the boolean gottemp set to true. this value of boolean makes the code written in the draw() to execute where the value gets printed on the screen using writetext() function. everything is going good. but now i want that the code running in the draw() to run in my own new thread. Because i want to write a camera visual code there.

    import processing.serial.*;
        Serial myPort;
    
    
        boolean gottemp= false;
        char tempdata;
        String tempstr="";
        void setup()
        {
         size(1000,1000);
         myPort = new Serial(this, "COM34", 9600);
    
        }
        void draw()
        {
           if(gottemp)
          { 
             tempstr=trim(tempstr);
             writeText(tempstr);
             tempstr="";
             gottemp=false;
          }
    
        }
    
    
        void serialEvent (Serial myPort){
          while(myPort.available()>0)
          {
            myPort.bufferUntil('\n');
            tempdata = myPort.readChar();
            tempstr +=tempdata;
         if((tempdata=='\n')&&(tempstr.length()!=0))
           {
              gottemp= true;
           }
          }
        }
    
        void writeText(String textToWrite){
    
              strokeWeight(5);
              fill(#5E5A64);
              rect(270,60,120,100);
              fill(0);
              smooth();
              textSize(20);
              text(textToWrite, 300, 100);   
        }
    
  • edited March 2015

    @GoToLoop converted the code above to this one below. But there are some amendments required.Like how to start this thread. Pls help make them

    import processing.serial.*;
    Serial myPort;
    MyThread thread;
    boolean gottemp= false;
    char tempdata;
    String tempstr="";
     void setup()
     {
       size(1000,1000);
       myPort = new Serial(this, "COM34", 9600);
       thread =new MyThread();
       thread.start();
    
     }
     void draw()
     {
    
     }
     void serialEvent (Serial myPort){
      while(myPort.available()>0)
      {
         myPort.bufferUntil('\n');
         tempdata = myPort.readChar();
         tempstr +=tempdata;
       if((tempdata=='\n')&&(tempstr.length()!=0))
           {
               gottemp= true;
           }
        }
      }
    
       void writeText(String textToWrite)
               {
    
                      strokeWeight(5);
                      fill(#5E5A64);
                      rect(270,60,120,100);
                      fill(0);
                      smooth();
                      textSize(20);
                      text(textToWrite, 300, 100);   
                }
    
    
            public class MyThread extends Thread
             {
             boolean gottemp;
               public MyThread(boolean gottemp){
                this.gottemp=gottemp; 
               }
                 public void start()
               {
                 super.start();
               }
               public void run()
               {
                  if(gottemp)
                  { 
                     tempstr=trim(tempstr);
                     writeText(tempstr);
                     tempstr="";
                     gottemp=false;
                  }
    
               }
             }
    
  • edited March 2015

    Compare your MyThread's run() method:

    public void run() {
      if (gottemp) {
        tempstr = trim(tempstr);
        writeText(tempstr);
        tempstr = "";
        gottemp = false;
      }
    }
    

    w/ function myThread() from my thread("") usage example:

    void myThread() {
      for (;; delay(1000))  print(mouseX + "\t");
    }
    

    If you spotted right, it's the lack of an infinite loop wrap up! :-\"
    Remember, once run() reaches the end, the Thread instance is over and can't even be restarted! :-S

  • edited March 2015

    hi @GoToLoop if i run my code i get error for the thread =new MyThread(); i understand that i have to put the void run in the infinite loop. But problem may be with how to call this thread. if the problem would have been the non usage of infinite loop the code should have run for once. Pls copy the code in ur processing ide. you will find red mark under line 11.

  • edited March 2015

    Indeed I didn't run your code b/c I've spotted the lack of an infinite loop inside its run() method.
    Problem is you specified a constructor for your class MyThread, demanding a boolean to be passed to it!
    Just delete the constructor. And while you're at it, delete your empty start() too! ;-)

  • I did what you said. but now it is throwing null pointer exception.

    import processing.serial.*;
    Serial myPort;
    MyThread thread;
    boolean gottemp= false;
    char tempdata;
    String tempstr="";
     void setup()
     {
       size(1000,1000);
       myPort = new Serial(this,"COM14", 9600);
    
       thread.start();
    
     }
     void draw()
     {
    
     }
     void serialEvent (Serial myPort){
      while(myPort.available()>0)
      {
         myPort.bufferUntil('\n');
         tempdata = myPort.readChar();
         tempstr +=tempdata;
       if((tempdata=='\n')&&(tempstr.length()!=0))
           {
               gottemp= true;
           }
        }
      }
    
       void writeText(String textToWrite)
               {
    
                      strokeWeight(5);
                      fill(#5E5A64);
                      rect(270,60,120,100);
                      fill(0);
                      smooth();
                      textSize(20);
                      text(textToWrite, 300, 100);   
                }
    
    
            public class MyThread extends Thread
             {
             boolean gottemp;
               public MyThread(boolean gottemp){
                this.gottemp=gottemp; 
               }
    
               public void run()
               {
                 while(true)
                 {
                  if(gottemp)
                  { 
                     tempstr=trim(tempstr);
                     writeText(tempstr);
                     tempstr="";
                     gottemp=false;
                  }
                 }
    
               }
             }
    
  • edited March 2015
    • I meant deleting the constructor inside class MyThread as you had done already w/ start().
    • Of course we still gotta use new in order to instantiate MyThread!
    • And place some delay() inside your infinite loop lest your CPU's gonna "fry"! >:)
  • edited March 2015

    oh! its getting confusing. Is this what u mean. it is saying sketch1345.MyThread is undefined. :(

    `import processing.serial.*;
    Serial myPort;
    MyThread thread;
    boolean gottemp= false;
    char tempdata;
    String tempstr="";
     void setup()
     {
       size(1000,1000);
       myPort = new Serial(this,"COM14", 9600);
       thread =new MyThread();
       thread.start();
    
     }
     void draw()
     {
    
     }
     void serialEvent (Serial myPort){
      while(myPort.available()>0)
      {
         myPort.bufferUntil('\n');
         tempdata = myPort.readChar();
         tempstr +=tempdata;
       if((tempdata=='\n')&&(tempstr.length()!=0))
           {
               gottemp= true;
           }
        }
      }
    
       void writeText(String textToWrite)
               {
    
                      strokeWeight(5);
                      fill(#5E5A64);
                      rect(270,60,120,100);
                      fill(0);
                      smooth();
                      textSize(20);
                      text(textToWrite, 300, 100);   
                }
    
    
            public class MyThread extends Thread
             {
             boolean gottemp;
               public MyThread(boolean gottemp){
    
               }
    
               public void run()
               {
                 while(true)
                 {
                  if(gottemp)
                  { 
                     tempstr=trim(tempstr);
                     writeText(tempstr);
                     tempstr="";
                     gottemp=false;
                  }
                 }
    
               }
             }`
    
  • edited March 2015

    I would be greatful if u could make a mockup. where i cud fill in my pieces of code. #-o i hope i am not bothering u much. thanks for trying hard to fix things ^:)^

  • edited March 2015

    Since I don't have the Serial hardware, most I can do is mockups! 8-|
    I dunno whether it's gonna work, but here's my tweaked version: :-\"

    // forum.processing.org/two/discussion/9707/
    // creating-threads-in-processing
    
    import processing.serial.Serial;
    
    volatile boolean gotTemp;
    String txt = "";
    
    void setup() {
      size(600, 250, JAVA2D);
      smooth(4);
      noLoop();
    
      stroke(0);
      strokeWeight(5);
    
      textSize(20);
      textAlign(LEFT, BASELINE);
    
      new Serial(this, "COM14", 9600).bufferUntil(ENTER);
      new MyThread().start();
    }
    
    void draw() {
      background(0300);
    
      fill(#5E5A64);
      rect(270, 60, 120, 100);
      fill(0);
      text(trim(txt), 300, 100);
    
      txt = "";
    }
    
    void serialEvent(Serial port) {
      char c = '\0';
    
      if ("".equals(txt))  while (port.available() > 0)  txt += c = port.readChar();
    
      if (c == ENTER & txt.length() != 0)  gotTemp = true;
    }
    
    class MyThread extends Thread {
      void run() {
        for (;; delay(100))  if (gotTemp) {
          gotTemp = false;
          redraw();
        }
      }
    }
    
  • edited March 2015

    Since serialEvent() already happens in a separate Thread (or not), you don't need your own Thread class
    nor even use thread("") I guess: (:|

    // forum.processing.org/two/discussion/9707/
    // creating-threads-in-processing
    
    import processing.serial.Serial;
    
    volatile boolean drawn;
    String txt = "";
    
    void setup() {
      size(600, 250, JAVA2D);
      smooth(4);
      noLoop();
    
      stroke(0);
      strokeWeight(5);
    
      textSize(20);
      textAlign(LEFT, BASELINE);
    
      new Serial(this, "COM14", 9600).bufferUntil(ENTER);
    }
    
    void draw() {
      background(0300);
    
      fill(#5E5A64);
      rect(270, 60, 120, 100);
      fill(0);
      text(txt, 300, 100);
    
      txt = "";
      drawn = true;
    }
    
    void serialEvent(Serial port) {
      char c = '\0';
    
      while (drawn && port.available() > 0) {
        txt += c = port.readChar();
    
        if (c == ENTER) {
          drawn = false;
          txt = trim(txt);
          redraw();
          return;
        }
      }
    }
    

    P.S.: Just found out that even though Serial runs under a separate Thread,
    its callback serialEvent() is delegated to the sketch's "Animation" Thread.
    It registers itself (via registerMethod() method) over sketch's pre() & dispose() call backs.

  • edited March 2015

    A potential simplification of serialEvent() callback.
    Even less sure whether it's got any chance to work though: :(|)

    P.S.: If Serial depends on pre(), which is called just before draw(), noLoop() + redraw() combo isn't gonna work!
    So I had to remove that approach! Ignore the other examples! =(

    // forum.processing.org/two/discussion/9707/
    // creating-threads-in-processing
    
    import processing.serial.Serial;
    
    volatile boolean drawn;
    String txt = "";
    
    void setup() {
      size(600, 250, JAVA2D);
      smooth(4);
      frameRate(20);
    
      stroke(0);
      strokeWeight(5);
    
      textSize(20);
      textAlign(LEFT, BASELINE);
    
      new Serial(this, "COM14", 9600).bufferUntil(ENTER);
    }
    
    void draw() {
      if (drawn)  return;
    
      background(0300);
    
      fill(#5E5A64);
      rect(270, 60, 120, 100);
      fill(0);
      text(txt, 300, 100);
    
      txt = "";
      drawn = true;
    }
    
    void serialEvent(Serial port) {
      if (drawn) {
        txt = port.readString().trim();
        drawn = false;
      }
    }
    
  • edited March 2015
    • After perusing Serial's library further, just found out I'm wrong again! 3:-O
    • serialEvent() is indeed called back from another Thread.
    • It's another callback called serialAvailable() that is called via sketch's pre() callback.
    • I've just scrambled those 2 callbacks when I was studying the library!
    • In short, it means that noLoop() + redraw() is once again possible! :-bd

    // forum.processing.org/two/discussion/9707/
    // creating-threads-in-processing
    
    import processing.serial.Serial;
    
    volatile boolean drawn;
    String txt = "";
    
    void setup() {
      size(600, 250, JAVA2D);
      smooth(4);
      noLoop();
      frameRate(30);
    
      stroke(0);
      strokeWeight(5);
    
      textSize(20);
      textAlign(LEFT, BASELINE);
    
      new Serial(this, "COM14", 9600).bufferUntil(ENTER);
    }
    
    void draw() {
      background(0300);
    
      fill(#5E5A64);
      rect(270, 60, 120, 100);
      fill(0);
      text(txt, 300, 100);
    
      txt = "";
      drawn = true;
    }
    
    void serialEvent(Serial port) {
      if (drawn) {
        txt = port.readString().trim();
        drawn = false;
        redraw();
      }
    }
    
  • Thanks. Let me try this and i will revert back. i have sent you a link. if you could pls visit that http://forum.processing.org/two/discussion/9840/i-want-to-display-the-temperature-and-video-but-video-is-hanging#latest

  • @GoToLoop. i tested the last code you posted. it is working well. However my problem for which i am trying the concept of threads remains the same. as i mentioned before i am taking the pain of playing with threads only because i want to display video from webcam in addition to the sensor value. This code suffices the condition but as soon as i will add the code for video display it will go out of context. noloop() and redraw() will not allow me to run the video. I think probably i could not convey to you y i am going for threads, otherwise the code is ok

  • edited March 2015

    going back to the older approach look at the code below, i omitted the serial as you donot have a hardware. I am going one step at a time so that i don't confuse you and can understand better what u are trying to say. If you will run this code (now you will be able to since no serial here). The thread prints hello i am your loving thread once. If i change the value of global variable at the top. The thread does't execute. That means the passing of value to thread is happening. great!!!!!!!!

    MyThread thread;
    boolean gottemp=true;
    char tempdata;
    String tempstr="";
     void setup()
     {
       size(100,100);
    
       thread =new MyThread(gottemp);
          thread.start();
     }
     void draw()
     {
     }
     public class MyThread extends Thread
     {
       boolean gottemp;
       public MyThread(boolean gottemp){
       this.gottemp=gottemp; 
       }
       public void start()
       {
        super.start();
       }
       public void run()
        {
          while(true)
           {
            if(gottemp)
              { 
               print("hello i am your loving thread");
               gottemp=false;
              }
           }
         }
     }
    

    if you went through this code now see the next post.

  • Next hurdle is to automate this passing from Serial function to the thread. The SeriaEvent() function by default returns the value of the gottemp to the draw(). and we don't need to define any return type.look at the code below. But since now we have to return the value to the thread. I think we need to make two amendments one is changing the function definition from void to boolean and adding a return at end. Look at the code below i did this.

    import processing.serial.*;
    Serial myPort;
    MyThread thread;
    boolean gottemp= false;
    char tempdata;
    String tempstr="";
     void setup()
     {
       size(100,100);
        myPort = new Serial(this,"COM14", 9600);
       thread =new MyThread(gottemp);
          thread.start();
     }
     void draw()
     {
    
    
     }
    
     boolean serialEvent (Serial myPort){
      while(myPort.available()>0)
      {
         myPort.bufferUntil('\n');
         tempdata = myPort.readChar();
         tempstr +=tempdata;
       if((tempdata=='\n')&&(tempstr.length()!=0))
           {
               gottemp= true;
               print("fromSerial");// debuging text
               println(tempstr);
           }
        }
        return gottemp;
      }
      public class MyThread extends Thread
             {
             boolean gottemp;
               public MyThread(boolean gottemp){
                this.gottemp=gottemp; 
               }
                  public void start()
               {
                 super.start();
              }
               public void run()
               {
                 while(true)
                 {
                  if(gottemp)
                  { 
                     print("from thread");// debugging text
                     println(tempstr);
                     gottemp=false;
                  }
                 }
             }
             }
    

    but unfortunatly on the console i am getting the debugging text i wrote in the serial function but not getting the debugging text from thread. What am i missing?

Sign In or Register to comment.