1

好的,所以我有一个 GUI Java 应用程序,它允许用户在 5-500 个软件设备之间选择和启动,每个软件设备由一个线程表示。线程不断用信息更新 GUI。

用户可以选择线程并暂停、恢复或终止它们。

关于线程和线程池、中断、Future 的所有信息......我只是迷路了,想在互联网上放火=)

我需要的是一些关于标准前进方向的明确指导。我在这里有我的线程类的大纲。

这是一个很好的模板吗?如果没有请编辑。

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)。使用中断本身作为信号。这就是它在那里的原因!

这是一个具有任意数量Threads 的系统的简单示例:

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();
}

我们使用 anExecutorService来管理Threads - 你永远不应该Thread直接使用 s,这又被地雷所困扰。

ExecutorService要求运行任意数量的任务 - 您可以查看如何在循环中添加任务for

然后为添加的每个任务ExecutorService返回一个Future- 这些是任务的句柄。它们允许我们检查它们是否仍在进行/完成或遇到错误。

我们Map使用Future任务名称,然后允许用户有选择地从输入中终止任务。

您不能“暂停”和“恢复”a Thread(当然可以,但最好不要担心)。您只需在希望暂停任务时取消它,然后重新发出它以重新启动它。好消息是ExecutorService它将回收Thread任务正在运行的内容,因此您不会失去性能。

如果您从多个线程向Mapof发出命令,则Future需要一个ConcurrentHashMap.

一个常见的陷阱是假设您的应用程序将在ExecutorService运行时干净地退出。不是这种情况。ExecutorService产生非守护线程,因此应用程序在它们全部完成之前无法退出。你有两个选择;第一个有点hacky - 只需给ExecutorService你自己的ThreadFactory并制作Threads 守护进程,第二个是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 回答