Java 如何重新启动流
我有一张表格Java 如何重新启动流,java,multithreading,swing,Java,Multithreading,Swing,我有一张表格 public class MainFrame extends JFrame { private int colThread=0; MainThread mt=new MainThread("Поток - 1"); public MainFrame() { setSize(300,300); setLocationRelativeTo(null); setDefaultCloseOperation
public class MainFrame extends JFrame {
private int colThread=0;
MainThread mt=new MainThread("Поток - 1");
public MainFrame()
{
setSize(300,300);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jp = new JPanel();
JButton jb=new JButton("Запустить поток");
jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
jb.setText("Перезапустить поток");
colThread = colThread + 1;
if (!mt.isInterrupted())
{
mt.interrupt();
}
mt.start();
}
});
jp.add(jb);
add(jp);
}
}
我有一个线程类:
public class MainThread extends Thread{
private int summ;
private String threadName;
public MainThread(String threadName)
{
this.threadName = threadName;
}
@Override
public void run() {
summ = 0;
while(true)
{
summ = summ +1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.threadName + " " + summ);
}
}
}
我的主要课程是:
public class MainClass {
public static void main(String[] args) {
MainFrame mf = new MainFrame();
mf.setVisible(true);
}
}
问题是单击按钮时如何重新启动线程执行。以这种形式执行程序时,会发生错误,但这是可以理解的,因为线程工作,所以不清楚中断()为什么不工作?来自:
多次启动线程是不合法的。特别是,线程一旦完成执行,就不能重新启动
但您可以创建Runnable的单个实现,并将其反复传递给线程构造函数:
public class MainThread implements Runnable {
然后在大型机类中,执行以下操作:
public class MainFrame extends JFrame {
private int colThread=0;
private MainThread task = new MainThread("Поток - 1");
private Thread mt = null;
// ...
public void actionPerformed(ActionEvent arg0) {
jb.setText("Перезапустить поток");
colThread = colThread + 1;
if (mt != null && !mt.isInterrupted())
{
mt.interrupt();
}
mt = new Thread(task);
mt.start();
请注意,螺纹体负责在中断时干净地退出。中断应始终被视为停止正在执行的操作的请求:
while(true)
{
summ = summ +1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break; // Someone wants this method to exit!
}
System.out.println(this.threadName + " " + summ);
}
更好的方法是将while
循环放在try/catch中:
try {
while(true)
{
summ = summ +1;
Thread.sleep(1000);
System.out.println(this.threadName + " " + summ);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
这将使循环在中断时自动退出。因此,为了维护可运行的
的单个实例,您可以在需要时将其工作安排给它。类似于在单个线程上调度相同的Runnable
您应该将整个try-catch块放在while
循环之外,因为中断意味着线程的运行时突然结束,因此线程在结束之前应该采取最后的操作来放弃/处置其资源
然后,您还可以添加一个布尔
变量,指示线程
应该终止还是继续工作。此变量在while
循环的条件下运行。这里的区别在于,我们不中断线程
,而是等待工作的关键部分完成,然后在正常情况下退出循环(之后也会处理资源)
基本上,用户的经验是中断方法杀死了中间的工作,而正常的终止需要更多的时间,但是优雅。
将这些注释放在一起,可以得到如下代码:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main2 {
public static class DisposableRunnable implements Runnable {
private boolean on = true;
@Override
public void run() {
try {
while (isOn())
doSomeWork();
System.out.println(Thread.currentThread().getName() + " is stopped gracefully.");
}
catch (final InterruptedException ix) {
System.out.println(Thread.currentThread().getName() + " is stopped abruptly: " + ix);
}
finally {
dispose();
}
}
//Do whatever work the thread has to do, in this method:
private void doSomeWork() throws InterruptedException {
for (int i = 0; i < 5; ++i) {
System.out.println("Working " + i + "...");
Thread.sleep(500); //Delay a bit, to simulate a lengthy work in progress.
}
}
private void dispose() {
//Relinquish resources here...
}
public synchronized boolean isOn() {
return on;
}
public synchronized void stop() {
on = false;
}
}
public static class MainFrame extends JFrame {
private final Thread mt;
private final DisposableRunnable run;
public MainFrame() {
run = new DisposableRunnable();
mt = new Thread(run);
final JPanel jp = new JPanel();
final JButton jb1 = new JButton("Click to stop.");
final JButton jb2 = new JButton("Click to interrupt.");
jb1.addActionListener(e -> {
run.stop();
jb1.setText("Stopped.");
jb1.setEnabled(false);
jb2.setEnabled(false);
});
jb2.addActionListener(e -> {;
mt.interrupt();
jb2.setText("Interrupted");
jb1.setEnabled(false);
jb2.setEnabled(false);
});
jp.add(jb1);
jp.add(jb2);
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.getContentPane().add(jp);
super.pack();
super.setLocationRelativeTo(null);
}
public void startOnce() {
mt.start();
setVisible(true);
}
}
public static void main(final String[] args) {
new MainFrame().startOnce();
}
}
import javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公共类Main2{
公共静态类DisposableRunnable实现Runnable{
private boolean on=true;
@凌驾
公开募捐{
试一试{
while(isOn())
doSomeWork();
System.out.println(Thread.currentThread().getName()+“正常停止”);
}
捕获(最终中断异常ix){
System.out.println(Thread.currentThread().getName()+)突然停止:“+ix”;
}
最后{
处置();
}
}
//使用以下方法执行线程必须执行的任何工作:
私有void doSomeWork()引发InterruptedException{
对于(int i=0;i<5;++i){
System.out.println(“工作“+i+”);
Thread.sleep(500);//稍微延迟一点,以模拟正在进行的冗长工作。
}
}
私有无效处置(){
//放弃这里的资源。。。
}
公共同步布尔值(){
回报;
}
公共同步无效停止(){
开=假;
}
}
公共静态类大型机扩展JFrame{
私有最终线程mt;
私人最终可处置运行;
公共主机(){
run=新的可处置runnable();
mt=新螺纹(运行);
final JPanel jp=新的JPanel();
final JButton jb1=新JButton(“单击停止”);
final JButton jb2=新JButton(“单击以中断”);
jb1.addActionListener(e->{
run.stop();
jb1.setText(“停止”);
jb1.setEnabled(false);
jb2.setEnabled(false);
});
jb2.addActionListener(e->{;
mt.中断();
jb2.setText(“中断”);
jb1.setEnabled(false);
jb2.setEnabled(false);
});
jp.add(jb1);
jp.add(jb2);
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.getContentPane().add(jp);
super.pack();
super.setLocationRelativeTo(空);
}
公共无效startOnce(){
mt.start();
setVisible(真);
}
}
公共静态void main(最终字符串[]args){
新主机().startOnce();
}
}
这里的区别在于,我们只创建了一个Runnable
实例(以及运行Runnable
的线程的一个实例)
还要注意,doSomeWork
方法的实现非常简单,它甚至不会抛出InterruptedException
,这意味着停止线程
的唯一正式方法是设置我们所说的布尔
标志(在本例中是on
变量)设置为false
并等待最后一项工作(即doSomeWork
方法)完成。如果您想在用户单击JButton
时终止main线程并重新启动它,那么调用方法interrupt()
是不可行的。你看到这个问题了吗?不,对象必须相同,您必须运行start()方法。您是说您被要求必须在同一线程对象上多次调用start()
?是的,对象不能更改,因为我理解,使用您的解决方案,每次用户单击JButton
时,都会启动一个新线程,但这些线程都不会停止