0

3 つのスレッドでリソースを共有するのに問題があります...

 public class Subject{

        int i;
        boolean valueSet1 = false;
        boolean valueSet2 = true;
        boolean valueSet3 = true;

    void put(int i){

        while(valueSet1){
            try{
                wait();
               }catch(InterruptedException e){
                    System.out.println("Producer thread interrupted");
                }
            }
            System.out.println("Producer thread wakesup");
            valueSet1=true;
            valueSet2=false;
            this.i=i;        
            System.out.println("Put: "+i);
            notify();
        }


    void makesquare(){

            int a;   
            while(valueSet2){
                try{
                    System.out.println("Convertor thread goin to sleep");
                    wait();
                }catch(InterruptedException e){
                    System.out.println("Convertor thread interrupted");
                }
            }       
            System.out.println("Convertor thread wakesup");
            valueSet2 = true;
            valueSet3=false;
            a = this.i;
            this.i = a*a;
            System.out.println("Made: "+i);        
            notify();
    }

    void get(){

           while(valueSet3){
                try{
                    System.out.println("Consumer thread goin to sleep");                
                    wait();
                }catch(InterruptedException e){
                    System.out.println("Consumer thread interrupted");
                }
            }
           System.out.println("Consumer thread wakesup");
           valueSet3 = true;
           valueSet1 = false;
           System.out.println("Got: "+i);
           notify();       
    }

    }

    class Producer implements Runnable{

        Subject q;    
        Thread t;
        String msg; 
        Producer(Subject q, String msg){
            this.q=q;
            this.msg = msg;
            t = new Thread(this, this.msg);
        }
        @Override
        public void run(){
            int i=2;
            while(true){
                synchronized(q){
                q.put(i++);
                }
            }
        }
    }
    class Consumer implements Runnable{

        Subject q;    
        Thread t;
        String msg;
        Consumer(Subject q,String msg){
            this.q = q;
            this.msg = msg;
            t = new Thread(this, this.msg);
        }
        @Override
        public void run(){
            while(true){
                synchronized(q){
                q.get();
                }
            }
        }
    }

    class Convertor implements Runnable{
        Subject q;   
        Thread t;
        String msg;
        Convertor(Subject q, String msg){
            this.q=q;
            this.msg = msg;
            t = new Thread(this, this.msg);    
        }
        @Override
        public void run(){
            while(true){
                synchronized(q){
                q.makesquare();
                }
            }
        }
    }

プログラムには 3 つのスレッドがあります。1 つのスレッドが生成し、別のスレッドが生成量の 2 乗を作成します。最後のスレッドは平方積を消費しますが、それらはすべて同じオブジェクトを共有します。

    public class Thread3way {

        public static void main(String[] args) {
           Subject q = new Subject();
           Producer P = new Producer(q, "producer");
           Convertor Cv = new Convertor(q, "convertor");
           Consumer Cs = new Consumer(q, "consumer");
           P.t.start();
           Cv.t.start();
           Cs.t.start();
        }
    }
4

2 に答える 2

0

ループは完全に正しくありません。変更を行う前にwait、条件が真になるまでループを続ける必要があります。私はこのようにします(列挙型を使用して物事を明確にします):State

public class Subject {
    static enum State { EMPTY, WAITING_TO_SQUARE, WAITING_TO_GET };
    State state;
    int value;

    public synchronized void put(int i) {
        while (state != State.EMPTY) {
            try {
                wait();
            }catch(InterruptedException e) {
                System.out.println("Put interrupted");
            }
        }
        value = i;
        state = State.WAITING_TO_SQUARE;
    }
}

コメント提供者が指摘したように、呼び出しsynchronized(q)の前後で2回同期したり、メソッドを宣言したりする必要はありません。両方は必要ありません。Subjectsynchronized

Runnables明示的に使用する必要はありません。 Producer、、、ConvertorおよびConsumer Threadsを直接作成するだけです。tそうすれば、フィールドは不要になり、のようなスレッドを開始できますP.start()

于 2012-09-13T16:40:47.763 に答える
0

3 つのステージである種のパイプラインを実行しているように思えます。次のメリットを享受してみませんかExecutorService:

class ConvertorTask implements Runnable {

    private int number;
    private static ExecutorService consumer = Executors.newSingleThreadExecutor();

    public ConvertorTask(int number) {
        this.number = number;       
    }

    public void run() {
        consumer.submit(new ConsumerTask(number * number));
    }
}

class ConsumerTask implements Runnable {

    private int number;

    public ConsumerTask(int number) {
        this.number = number;       
    }

    public void run() {
        System.out.println(number);
    }
}

class Producer implements Runnable {

    private ExecutorService convertor = Executors.newSingleThreadExecutor();

    public void run() {
        int i = 0;
        while(true) {           
            convertor.submit(new ConvertorTask(i++));
        }
    }
}

public class Test {

    public static void main(String[] args) throws InterruptedException {        
        Thread t = new Thread(new Producer());
        t.start();
    }
}
于 2012-09-13T16:54:21.963 に答える