线程小程序不工作

时间:2015-05-15 01:12:45

标签: java multithreading while-loop applet

我一直在研究这个问题,并且无法弄清楚为什么这个applet无法正常工作:

我在applet中实例化了两个线程。 我创建了两个按钮 - 开始和停止,它们应该更改标志值以结束我的线程中的while()循环。小程序没有响应任何一个按钮。任何建议,任何人?谢谢你的时间!

这是小程序......

package prodcons;

import java.applet.Applet;
import java.util.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MyTableSetting extends Applet {
Soup s;                                             // we will show     the soup bowl with the soup's alphabet pieces
int bowlLength = 150;                               // bowl's dimensions as variables in case we want to change it
int bowlWidth = 220;
int bowlX = 60;
int bowlY = 10;
Producer p1;
Consumer c1;



public void init(){
    setSize(400,200);                                 // make the applet size big enough for our soup bowl
    s = new Soup();                                   // instantiate the Soup
    p1 = new Producer(this, s);              // declare and instantiate one producer thread - state of NEW
    c1 = new Consumer(this, s);              // declare and instantiate one consumer thread - state of NEW
    p1.start();                                       // start the producer thread
    c1.start();                                       // start the consumer thread

    Button stop = new Button("Stop");
    stop.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Producer.producerRunning = false;
            Consumer.consumerRunning = false;
            Soup.clearBuffer();
        }
    });
    add(stop);

    Button start = new Button("Start");
    start.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Producer.producerRunning = true;
            Consumer.consumerRunning = true;
            p1.run();
            System.out.println("heyyy");
            c1.run();
        }
    });
    add(start);
}

public void paint(Graphics g){                        // first we make the bowl and spoon
    int x;
    int y;
    g.setColor(Color.orange);
    g.fillOval(bowlX, bowlY, bowlWidth, bowlLength);  // the bowl
    g.setColor(Color.cyan);
    g.fillOval(10, 25, 40, 55);                       // the spoon
    g.fillOval(25, 80, 8, 75);
    g.setColor(Color.black);                          // black outlines for the dinnerware
    g.drawOval(10, 25, 40, 55);
    g.drawOval(25, 80, 8, 75);
    g.drawOval(bowlX,bowlY, bowlWidth, bowlLength);
    ArrayList <String> contents = s.getContents();  // get contents of the soup
    for (String each: contents){                      // individually add each alphabet piece in the soup
        x = bowlX + bowlWidth/4 +(int)(Math.random()* (bowlWidth/2));  // put them at random places to mimic stirring
        y = bowlY + bowlLength/4 + (int)(Math.random()* (bowlLength/2));
        Font bigFont = new Font("Helvetica", Font.BOLD, 20);
        g.setFont(bigFont);
        g.drawString(each, x, y);
    }
}   

}

这些是主题:

package prodcons;

class Consumer extends Thread {
private Soup soup;
private MyTableSetting bowlView;
static boolean consumerRunning = true;

public Consumer(MyTableSetting bowl, Soup s) {
    bowlView = bowl;                               // the consumer is given the GUI that will show what is happening
    soup = s;                                      // the consumer is given the soup--the monitor
}

public void run() {
    System.out.println("consuming: "+consumerRunning);
    String c;
    try {
    while(consumerRunning) {              // stop thread when know there are no more coming; here we know there will only be 10
        c = soup.eat();                            // eat it from the soup
        System.out.println("Ate a letter: " + c);  // show what happened in Console
        bowlView.repaint();                        // show it in the bowl  

            sleep((int)(Math.random() * 3000));    // have consumer sleep a little longer or sometimes we never see the alphabets!
    }    
    } catch (InterruptedException e) {
            this.interrupt();
        }
    }

}

和此:

package prodcons;

class Producer extends Thread {
private Soup soup;
private String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private MyTableSetting bowlView;
static boolean producerRunning = true;

public Producer(MyTableSetting bowl, Soup s) {
    bowlView = bowl;        // the producer is given the GUI that will show what is happening
    soup = s;               // the producer is given the soup--the monitor
}

public void run() {
    String c;
    try {
    while (producerRunning) {                           // only put in 10 things so it will stop
        System.out.println("thikns producer != null");
        c = String.valueOf(alphabet.charAt((int)(Math.random() * 26)));   // randomly pick a number to associate with an alphabet letter
        soup.add(c);                                            // add it to the soup
        System.out.println("Added " + c + " to the soup.");     // show what happened in Console
        bowlView.repaint();                                     // show it in the bowl  

            sleep((int)(Math.random() * 2000));  // sleep for a while so it is not too fast to see
    }
        } catch (InterruptedException e) {
            this.interrupt();
        }

}
}

这是“汤”类:

package prodcons;

import java.util.*;

public class Soup {
private static ArrayList <String> buffer = new ArrayList<String>();  // buffer holds what is in the soup
private int capacity = 6; 

public synchronized String eat() {      //this method can only be accessed by one thing at a time
     while(buffer.isEmpty()){                                              // cannot eat if nothing is there, so check to see if it is empty                                                 
            try {
                wait();                                                       // if so, we WAIT until someone puts something there
            } catch (InterruptedException e) {}                               // doing so temporarily allows other synchronized methods to run (specifically - add)
        }                                                                     // we will not get out of this while until something is there to eat
        String toReturn = buffer.get((int)(Math.random() * buffer.size()));   // get a random alphabet in the soup     
        buffer.remove(toReturn);                                              // remove it so no one else can eat it
        buffer.trimToSize();                                                  // reduce the size of the buffer to fit how many pieces are there
        notifyAll();                                                          // tell anyone WAITing that we have eaten something and are done
        return(toReturn);
}

public synchronized void add(String c) {
    while (buffer.size() == capacity) {
        try {
            wait();
        }
        catch (InterruptedException e) {}
    }
    buffer.add(c);
    notifyAll();
}

public ArrayList <String> getContents() {
    return buffer;
}

public static void clearBuffer() {
    buffer.clear();
}

}

非常感谢你!

1 个答案:

答案 0 :(得分:0)

您可以从启动按钮的事件处理程序直接在主UI线程上调用Producer和Consumer。这将产生的唯一影响是冻结整个应用程序。那是因为主UI线程完成了所有事情:事件处理,重新绘制等等。只要你坚持下去,就不会有事件处理,重新绘制等等。

你永远不应该在主UI线程上调用任何需要很长时间的东西。

但是,由于您已经在init方法中启动了线程,因此您无需在动作侦听器中调用run。你删除了这些电话:

Button start = new Button("Start");
    start.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Producer.producerRunning = true;
            Consumer.consumerRunning = true;
        }
    });

此外,你应该制作标志volatile,否则在另一个线程中可能看不到从一个线程对它们的更改:

volatile static boolean producerRunning = true;

(等)