好的,我有一个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个线程的最佳方法是什么?
非常感谢。
答案 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}}