Spring

다른 스레드에서 Java로 스레드를 일시 중지하고 다시 시작하는 방법

기록만이살길 2021. 3. 18. 05:06
반응형

다른 스레드에서 Java로 스레드를 일시 중지하고 다시 시작하는 방법

1. 질문(문제점):

Java Swing으로 응용 프로그램을 작성하고 있습니다. 내가 필요한 것은 그래픽 인터페이스의 버튼을 사용하여 "정교화"스레드를 중지 할 수있는 절차입니다.

여기 내가 필요한 것에 초점을 맞춘 간단한 프로젝트

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTextArea;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Nikola
 */
public class Main extends javax.swing.JFrame
{
    private MyThread THREAD;

    public Main()
    {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jButton1 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jButton1.setText("Pause Thread");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jTextArea1.setColumns(20);
        jTextArea1.setRows(5);
        jScrollPane1.setViewportView(jTextArea1);

        jButton2.setText("Resume Thread");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jButton3.setText("Start Thread");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButton3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 63, Short.MAX_VALUE)
                        .addComponent(jButton2)
                        .addGap(18, 18, 18)
                        .addComponent(jButton1))
                    .addComponent(jScrollPane1))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 244, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2)
                    .addComponent(jButton3))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt)
    {
        THREAD = new MyThread(jTextArea1);
        THREAD.start();
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
    {
        try
        {
            THREAD.pauseThread();
        }
        catch (InterruptedException ex)
        {
            ex.printStackTrace();
        }
    }

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt)
    {
        THREAD.resumeThread();
    }

    public static void main(String args[])
    {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try
        {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
            {
                if ("Nimbus".equals(info.getName()))
                {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        }
        catch (ClassNotFoundException ex)
        {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (InstantiationException ex)
        {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (IllegalAccessException ex)
        {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        catch (javax.swing.UnsupportedLookAndFeelException ex)
        {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable()
        {

            public void run()
            {
                new Main().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea jTextArea1;
    // End of variables declaration
}

class MyThread extends Thread
{
    JTextArea area;

    private final Object lock = new Object();

    public MyThread(JTextArea area)
    {
        super();
        this.area = area;
    }

    @Override
    public void run()
    {
        for(int i=0 ; ; i++)
            area.setText(i+"");
    }

    public void pauseThread() throws InterruptedException
    {
        synchronized(lock)
        {
            lock.wait();
        }
    }

    public void resumeThread()
    {
        synchronized(lock)
        {
            lock.notify();
        }
    }
}

질문은 간단합니다. 실제 애플리케이션에서 사용자는 몇 가지 옵션을 설정 한 다음 선택한 데이터를 정교화하는 스레드를 시작합니다.

사용자가 일시적으로 정교화를 중지하고 필요한 확인을 한 후 작업을 다시 시작할 수 있도록 "일시 중지"버튼을 제공하고 싶습니다.

내가 코딩 한 방식은 "정교화"가 아닌 그래픽 스레드입니다.

내 샘플 코드를 실행하고 "시작"을 누르면 텍스트 영역이 계산되기 시작합니다. 내가 필요한 최종 결과는 "일시 중지"버튼을 누르면 스레드가 "휴면"으로 이동하고 계산이 중지되고 "다시 시작"버튼을 누르면 스레드가 "깨어나고"텍스트 영역의 계산이 시작된다는 것입니다. 다시 계산합니다.

2. 해결방안:

당신은 할 수 확실히 당신이 원하는 것처럼 보이는 방법으로 서로 하나 개의 스레드를 일시 중지합니다.

대신해야 할 일은 일종의 플래그를 설정하여 다른 스레드가 중지되어야 함을 알리는 것 입니다. 문제의 스레드에는이 플래그를 확인하고 해당 작업이 발생하면 일시 중지하는 논리가 있어야합니다.

따라서이 특별한 경우에는 MyThread다음과 같이 변경하십시오 .

class MyThread extends Thread {

    private volatile boolean running = true; // Run unless told to pause

    ...

    @Override
    public void run()
    {
        for(int i=0 ; ; i++)
        {
            // Only keep painting while "running" is true
            // This is a crude implementation of pausing the thread
            while (!running)
                yield;

            area.setText(i+"");
    }

    public void pauseThread() throws InterruptedException
    {
        running = false;
    }

    public void resumeThread()
    {
        running = true;
    }

}

이것은 간결함을 위해 적절한 모니터 기반 수면 대신 일종의 스핀 락을 사용하는 조잡한 예입니다. 바라건대 스레드의 일시 중지를 제어하기 위해 플래그를 사용하는 방법에 대한 아이디어를 전달하기를 바랍니다.

setText호출이 아닌 블록 내에서 장기간 실행되는 단계 집합을 수행하는 경우 Thread.currentThread().interrupted()각 단계 사이 를 확인 하고 itnerrupt 플래그가 설정된 경우 루프를 종료하는 것이 좋습니다. 이것은 일반적으로 내장 블로킹 메소드 (예 : I / O)가 다른 스레드에 의해 인터럽트 될 수 있도록하는 것입니다. running플래그는 루프 당 하나만 검사 되기 때문에 각 루프에 대해 설정하는 것이별로 좋지 않습니다. 20 분이 소요됩니다.

65692124
반응형