0

I have a Scheduler class with a thread in charge of creating Process objects and I want to take the Process object as they are created and display the useful information to a JTextArea. However, when the Scheduler class creates the Process the JTextArea remains blank. How can i notify or update the JTextArea everytime a new Process is created? There is also an ArrayBlockingQueue that stores every Process until the CPU class executes it.

I have tried setting up Event listeners to try to capture when a process has been created.

public class Main {

    public static void main(String[] args) {



            Scheduler scheduler = new Scheduler();
            scheduler.createProcesses();

            SwingUtilities.invokeLater(new Runnable(){

                public void run(){
                    JFrame frame = new MainFrame();
                    frame.setVisible(true);
                    frame.setSize(500,500);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                }
            });

    }
 }




Main creates the Scheduler object and then calls createProcess(). Then it calls the SwingUtilities runnable thread.

import java.awt.BorderLayout;
import java.awt.Container;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.lang.Math;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Scheduler {
    private static final int MAX_QUEUE_SIZE = 1001;
    private CPU cpu;
    private MainFrame frame;
    ArrayBlockingQueue<Process> readyQueue;
    int time = 0;
    int pid = 1000;



    public Scheduler()
    {
        readyQueue = new ArrayBlockingQueue<Process>(MAX_QUEUE_SIZE, true);
        this.cpu = new CPU(this);
        frame = new MainFrame();

        }//end of constructor


    public void createProcesses()  //populate ready queue
    {


        new Thread(new Runnable() {
            @Override
            public void run() {
                // Create 1002 processes
                Scheduler.this.cpu.start();
                while(pid < 2002) {
                    Random rand = new Random();
                    int meanRunTime = 10;
                    int sd = 2;
                    // Random number following a Normal distribution
                    int runTime = (int) Math.round(rand.nextGaussian()) * sd + meanRunTime;
                    int meanDelayTime = 5;
                    sd = 1;
                    int arrivalDelayTime = (int) Math.round(rand.nextGaussian()) * sd + meanDelayTime;
                    //System.out.println(Scheduler.this.time);
                    try {
                            // Wait for process to arrive
                            Thread.sleep(arrivalDelayTime);
                            Scheduler.this.time += arrivalDelayTime;
                        } catch (InterruptedException e) {
                            System.out.println("Queue waiting for arival interrupted");
                        }

                    Process p = new Process(Scheduler.this.pid, Process.WAITING, (time), runTime);    //constructs Process


                    System.out.println(p.toString());
                    frame.setProcess(p);   //This is where I am attempting to pass the process to the frame however this does not seem to work


                    Scheduler.this.pid++;
                    try {
                    Scheduler.this.readyQueue.put(p);
                    } catch (InterruptedException e){
                        e.printStackTrace();
                    }

                }

            }

        }).start();

    }//end of create process

This is the scheduler class. Basically when it creates Process p i need it to tell the GUI about the newly created process so that it can be added to processTextArea

import java.awt.BorderLayout;
import java.awt.Container;
import java.util.concurrent.ArrayBlockingQueue;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;



public final class MainFrame extends JFrame{

    private Process process;





    public MainFrame(){

            //Layout of Frame
            setLayout(new BorderLayout());

            //Creation of Components that will go into the Frame
            JTextArea processTextArea = new JTextArea("Awaiting Completed Processes");

            while(process != null){
                processTextArea.setText(process.toString());
                process = null;
            }

            //Adds Compnents to the content frame
            Container c = getContentPane();
            c.add(processTextArea, BorderLayout.EAST);







    }



    public void setProcess(Process p){
        this.process = p;


    }

The MainFrame is the GUI class. At the moment the setProcess call made in the Scheduler class does give the MainFrame class a process object but only once. How can this be updated everytime a new Process is created?

I Wish to have the GUI fill up the processTextArea as new Process's are being created. What happens at the moment is The GUI frame pops up however nothing is being added to the processTextArea.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

0

This is the scheduler class. Basically when it creates Process p i need it to tell the GUI about the newly created process so that it can be added to processTextArea

I think the MainFrame object in Main and the MainFrame in Scheduler are two different reference? You should solve this first.

I Wish to have the GUI fill up the processTextArea as new Process's are being created. What happens at the moment is The GUI frame pops up however nothing is being added to the processTextArea.

Extract processTextArea to become the member of MainFrame, and to create a method like:

public void onProcessComplete(Process P) {
    synchronized (processTextArea) {
        processTextArea.append(process.toString());
    }
}

Whenever a Process is completed, invoke mainFrame.onProcessComplete(this). This should meet your needs.

Mr. Brickowski
  • 1,134
  • 1
  • 8
  • 20
  • Why are you recommending that a *new* JTextArea be created within the `onProcessComplete` method? Why not instead have the original poster declare and initialize a JTextArea in the MainFrame variable declaration section, and then append text to that JTextArea as needed? Also, your code does not appear to be Swing thread-safe -- have you considered that the Process might be calling Swing methods off of the Swing event thread? – Hovercraft Full Of Eels May 06 '19 at 03:18
  • You are right, I misunderstand the question. It should fill content to the text area not add a new one. Regarding the thread-safty, I apply it to the MainFrame. The source for Process is not shown, not consider that at the moment. – Mr. Brickowski May 06 '19 at 05:28
  • You are correct with the reference issue, but your handling of Swing threading is still incorrect. I refer you to [Lesson: Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for the details. – Hovercraft Full Of Eels May 16 '19 at 19:42