Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何重新启动流_Java_Multithreading_Swing - Fatal编程技术网

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
时,都会启动一个新线程,但这些线程都不会停止