-1

Javaのスレッドに問題があります。文字と数字を書くだけのクラス(クラスタスク)のスレッドのArrayListを持つクラスMainがあるプログラムを書きたいと思います。Object Mainは、ArrayListから1つのスレッドをウェイクアップし、同じオブジェクト(Main)が別のスレッドをスリープしている間に何かを実行させます。ただし、Main.ACTIVEをfalseに変更しても、一部のスレッドが終了しないという問題が1つあります。これはランダムであり、終了して次のように記述します。

私はgoodbay+キャラクターを言っています-そのようなsth

public class Main extends Thread {
    ArrayList<Thread> threads;
    static boolean ACTIVE = true;
    public Main() {
        super();
        threads = new ArrayList<Thread>();
    }

    public void run(){

        Object monitor = new Object();
        for (int i = 0; i <= 5; i++) {
            threads.add(new Thread(new Task(i + 65, monitor)));
        }

        long cT = System.currentTimeMillis();
        for (int i = 0; i < threads.size(); i++) {
            threads.get(i).start();
        }
        System.out.println("BEFORE synchronized(monitor)");
        synchronized(monitor){
            while (System.currentTimeMillis() - cT < 1000) {
                try{
                    monitor.notify();
                    Thread.sleep(50);
                    monitor.wait();
                } catch(Exception e){
                    e.printStackTrace();}
                }
                System.out.println("BEFORE ACTIVE= FALSE and after WHILE in Main");
                ACTIVE = false;
                for(int i  = 0; i < threads.size(); i++){
                    System.out.println(threads.get(i).getState());
                }
            }
            System.out.println("LAST COMMAND IN MAIN");
        }
    }

    public static void main(String[] args) {
        new Main().start();
        //new Thread(new Task(65)).start();
    }
}

そしてタスククラス

public class Task implements Runnable {
    int nr;
    char character;
    Object monitor;

    public Task(int literaASCII, Object monitor) {
        this.nr = 0;
        this.monitor = monitor;
        character = (char) (literaASCII);
    }

    @Override
    public void run() {
        synchronized (monitor) {
            while (Main.ACTIVE) {
                try {
                     System.out.println("ENTERING WHILE IN TASK");
                    monitor.wait();
                    System.out.print(nr + "" + character + ", ");
                    nr++;
                    int r = (int) ((Math.random() * 50) + 50); // <500ms,1000ms)
                    Thread.sleep(r);
                } catch (Exception e) {e.printStackTrace();}
                monitor.notify();
                 System.out.println("YYYYYYYYY");
            }
             System.out.println("AFTER WHILE IN Task");
        }
        System.out.println("I am saying goodbye " + character);
    }
}
4

3 に答える 3

4

java.util.concurrent特に、パッケージ内の最新の同時実行クラスを確認することをお勧めしますExecutorService。そして「Java Concurrency In Practice」を読んでください。

于 2012-05-14T12:24:35.367 に答える
3

ACTIVEあなたの問題は、としてマークする必要がある初心者向けvolatileです。複数のスレッドによって共有される変数は、その読み取りと書き込みの周りにメモリ バリアを設けるために、何らかの方法でそのようにsynchronizedマークする必要があります。volatile

ブールの観点からできるもう 1 つのことは、 のAtomicBoolean代わりにクラスを使用することvolatile booleanです。

の代わりに、 for eachオブジェクトを使用して、個々のタスクをよりきめ細かく制御し、「グローバル」変数を使用することstatic volatile booleanを検討できます。アクティブ フラグを設定するメソッドを追加することもできます。volatile booleanTaskMainstatictask.shutdown()

最後に、@duffmo が述べたように、常にExecutorService1 つのスレッドを実行したい場合は、スレッド プールの 1 つを使用することを常に検討する必要があります。のようなものExecutors.newFixedThreadPool(1)。しかし、常に 1 つのスレッドだけが必要かどうかはわかりません。を使用した場合は、ExecutorService次のmainようにします。

ExecutorService threadPool = Executors.newFixedThreadPool(1);
List<Future> futures = new ArrayList<Future>();
for (int i = 0; i <= 5; i++) {
    // the monitor would not be needed
    threadPool.submit(new Task(i + 65));
}
threadPool.shutdown();
for (Future future : futures) {
    // this waits for the working task to finish
    future.get();
}

ただし、バックグラウンド タスクを現在 で行っているように停止および開始する必要がある場合monitor、このモデルは機能しない可能性があります。

于 2012-05-14T12:24:27.993 に答える
0

今、naswer は

0A, 0B, 0C, 0D, 0E, 0F, 1A, 1B, 1C, 1D, 1E, 1F, 待機中 待機中 待機中 待機中 待機中 最後のコマンドをメインで待機中

スレッドを開始した後にスリープを追加しました

import java.util.ArrayList;

public class Main extends Thread {
ArrayList<Thread> threads;
volatile static boolean ACTIVE = true;
public Main() {
    super();
    threads = new ArrayList<Thread>();
}

 public void run(){

Object monitor = new Object();
for (int i = 0; i <= 5; i++) {
  threads.add(new Thread(new Task(i + 65, monitor)));
}

long cT = System.currentTimeMillis();
for (int i = 0; i < threads.size(); i++) {
  threads.get(i).start();
}
try{Thread.sleep(50);}catch(Exception e){e.printStackTrace();}
 //   System.out.println("BEFORE synchronized(monitor)");
synchronized(monitor){
  while (System.currentTimeMillis() - cT < 1000) {
      try{

    monitor.notify();
    Thread.sleep(500);

    monitor.wait();}catch(Exception e){e.printStackTrace();}
  }
   //    System.out.println("BEFORE ACTIVE= FALSE and after WHILE in Main");
  ACTIVE = false;
  for(int i  = 0; i < threads.size(); i++){
      System.out.println(threads.get(i).getState());
  }


}
System.out.println("LAST COMMAND IN MAIN");

  }


  public static void main(String[] args) {
     new Main().start();
    //new Thread(new Task(65)).start();

}

}

そしてTASK

public class Task implements Runnable {
int nr;
char character;
Object monitor;

public Task(int literaASCII, Object monitor) {
    this.nr = 0;
    this.monitor = monitor;
    character = (char) (literaASCII);
}

@Override
public void run() {
    synchronized (monitor) {
        while (Main.ACTIVE) {
            try {
//               System.out.println("ENTERING WHILE IN TASK");
                monitor.wait();
                System.out.print(nr + "" + character + ", ");
                nr++;
                int r = (int) ((Math.random() * 50) + 50); // <500ms,1000ms)

                Thread.sleep(r);
            } catch (Exception e) {e.printStackTrace();}
            monitor.notify();
    //       System.out.println("YYYYYYYYY");
        }
         System.out.println("AFTER WHILE IN Task");
    }
    System.out.println("I am saying goodbye " + character);
}

}

于 2012-05-15T00:30:13.093 に答える