线程模板

时间:2013-07-13 08:30:04

标签: java multithreading thread-safety threadpool

好的,我有一个GUI Java应用程序,允许用户在5-500个软件设备之间进行选择和启动,每个软件设备由一个Thread表示。线程不断用信息更新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个线程的最佳方法是什么?

非常感谢。

2 个答案:

答案 0 :(得分: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();
}

我们使用ExecutorService来管理Thread - 你永远不应该直接使用Thread,这再次受到地雷的困扰。

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

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

我们Map Future到任务名称,并允许用户从输入中选择性地终止任务。

你不能“暂停”和“恢复”Thread(你可以,但最好不要担心)。您只需在暂停时取消任务,然后重新发出该任务即可重新启动它。好处是ExecutorService将回收运行任务的Thread,这样你就不会失去性能。

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

一个常见的陷阱是假设您的应用程序将在ExecutorService运行时干净地退出。不是这种情况。 ExecutorService生成非守护程序线程,因此应用程序无法退出,直到它们全部完成。你有两个选择;第一个是有点hacky - 只需给ExecutorService你自己的ThreadFactory并制作Thread s守护进程,第二个是当你完成它时关闭ExecutorService正如我在例子中所说的那样。

答案 1 :(得分: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); }

可以改进一些伪代码:

{{1}}