1

OK ということで、ユーザーがそれぞれスレッドで表される 5 ~ 500 のソフトウェア デバイスを選択して起動できるようにする GUI Java アプリケーションを用意しました。スレッドは、情報を使用して GUI を継続的に更新します。

ユーザーは、スレッドを選択して一時停止、再開、または強制終了できます。

スレッドとスレッドプール、割り込み、未来に関するすべての情報....私は道に迷って、インターネットに火をつけたかった=)

私が必要としているのは、これを進めるための標準的な方法に関する明確なガイダンスです。ここに私のスレッドクラスの概要を以下に示します。

これは開始するのに適したテンプレートですか? そうでない場合は、編集してください。

package ACsimForm;

import java.util.Random;
import javax.swing.SwingUtilities;

public class Squeak implements Runnable {

    private  String name = "";  
    private  javax.swing.JTextArea ScroolPage;


        Squeak (String name, javax.swing.JTextArea MW )
        {
            this.value = true;
            this.name = name;
            this.ScroolPage = MW;
        }


         Random r = new Random();
         int num = r.nextInt(10-1) + 1;


    @Override
   public void run ()
        {                                 
            updateGUI("Thread "+name+" Loaded and Running");

            while(true)
            {
                updateGUI("New Data");

                try {                        
                      TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    updateGUI("Thread "+name+" Exiting!");
                    //return exits the method killing the thread
                    return;
                }                
            }                               
        }



 //this is the new way to communicate back to the GUI 
 private void updateGUI(final String foo) {
 SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          ScroolPage.append(foo+"\r\n");      
        }
      });
    }
    }

GUI からスレッドを強制終了または一時停止/再開できるように、最大​​ 500 のスレッドを追跡する最良の方法は何ですか?

どうもありがとう。

4

2 に答える 2

1

私はあなたRunnableがほとんどそこにいると思います。魔法のBoolean旗のアイデアを放棄してください - これは問題に悩まされています ( を読んでくださいvolatile)。割り込み自体をシグナルとして使用します。これがそこにある理由です!

Thread任意の数のsを持つシステムの簡単な例を次に示します。

private static final class Printer implements Runnable {

    private final String printMe;

    public Printer(String printMe) {
        this.printMe = printMe;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println(Thread.currentThread().getName() + "says: " + printMe);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException ex) {
                return;
            }
        }
    }
}

public static void main(String[] args) throws Exception {
    final ExecutorService executorService = Executors.newCachedThreadPool();
    final Map<Integer, Future<?>> futures = new HashMap<>();
    for (int i = 0; i < 10; ++i) {
        futures.put(i, executorService.submit(new Printer("Printer" + i)));
    }
    final Scanner scanner = new Scanner(System.in);
    while (true) {
        final String input = scanner.nextLine();
        if ("EXIT".equalsIgnoreCase(input)) {
            break;
        }
        final Integer threadToStop;
        try {
            threadToStop = Integer.parseInt(input);
        } catch (NumberFormatException ex) {
            System.out.println("Not a number");
            continue;
        }
        final Future<?> f = futures.remove(threadToStop);
        if (f == null) {
            System.out.println("Not a valid thread");
            continue;
        }
        f.cancel(true);
    }
    executorService.shutdownNow();
}

ExecutorServicesを管理するためにを使用しThreadます - s を直接使用するべきではありませんThread。これも地雷に悩まされています。

ExecutorService、任意の数のタスクを実行するよう求められforます。ループ内にタスクを追加する方法を確認できます。

次に、追加されたタスクごとに をExecutorService返します- これらはタスクへのハンドルです。Futureそれらは、まだ進行中/完了しているかどうか、またはエラーが発生したかどうかを確認することができます。

タスク名にs を追加MapFuture、ユーザーが入力からタスクを選択的に削除できるようにします。

「一時停止」と「再開」はできませんThread(できますが、気にしない方がよいでしょう)。一時停止したいときにタスクをキャンセルし、再発行して再開するだけです。良いことは、タスクが実行されていたExecutorServiceがリサイクルされるため、パフォーマンスが低下しないことです。Thread

複数のスレッドからMapof にコマンドを発行する場合は、 .FutureConcurrentHashMap

よくある落とし穴は、ExecutorService実行中にアプリケーションが正常に終了すると想定することです。これはそうではありません。ExecutorService非デーモン スレッドが生成されるため、すべての処理が完了するまでアプリケーションを終了できません。2 つのオプションがあります。1 つ目は少しハックですExecutorService。独自のものを指定ThreadFactoryしてThreads デーモンを作成するだけです。2 つ目はExecutorService、例で示したように、使い終わったら をシャットダウンすることです。

于 2013-07-13T08:52:55.470 に答える
0

これは完全な答えではありませんが、物事を成し遂げるためのいくつかのヒントです。

ExecutorServiceスレッドとそれらには を使用する必要があり.submit()ます。それらを登録して利用できるようにするには、たとえば名前でMap<String, Future<?>>.

いくつかの疑似コードは、改善される可能性があります:

@GuardedBy("this") // see JSR 305
final Map<String, Future<?>> allSqueaks
    = new HashMap<String, Future<?>>();
final ExecutorService service
    = Executors.newCachedThreadPool();

// Registering:
public synchronized void registerSqueak(final Squeak squeak)
{
    allSqueaks.put(squeak.getName(), service.submit(squeak));
}

// Cancelling:
public synchronized void cancelSqueakByName(final String name)
{
    // Note: deal with non existing name if it can happen
    final Future<?> victim = allSqueaks.remove(name);
    victim.cancel(true);
}
于 2013-07-13T09:01:20.260 に答える