Swingworker 스레딩 모드 사용
스윙 개발자가 동시성을 신중하게 사용하는 것이 매우 중요합니다. 좋은 스윙 프로그램은 동시성 메커니즘을 사용하여 응답을 잃지 않는 사용자 인터페이스를 생성합니다. 어떤 종류의 사용자 상호 작용에 관계없이 프로그램이 항상 응답 할 수 있습니다. 반응 형 프로그램을 만들려면 개발자는 스윙 프레임 워크에서 멀티 스레딩을 사용하는 방법을 배워야합니다.
스윙 개발자는 다음 유형의 스레드를 처리합니다.
(1) 초기 스레드, 이러한 스레드는 초기화 응용 프로그램 코드를 실행합니다.
(2) 이벤트 디스패치 스레드, 모든 이벤트 처리 코드는 여기에서 실행됩니다. 스윙 프레임 워크와 상호 작용하는 대부분의 코드는이 스레드를 실행해야합니다.
(3) 배경 스레드라고도하는 작업자 스레드는 모든 시간 소모 작업을 수행합니다.
개발자는 코드에서 이러한 스레드를 명시 적으로 만들 필요가 없습니다. 런타임 또는 스윙 프레임 워크에서 제공합니다. 개발자의 임무는 이러한 스레드를 사용하여 반응적이고 지속적인 스윙 프로그램을 만드는 것입니다.
Java 플랫폼에서 실행되는 다른 모든 프로그램과 마찬가지로 Swing 프로그램은 추가 스레드 및 스레드 풀을 만들 수 있으며,이 기사에서 소개 될 접근 방식을 사용해야합니다. 이 기사에서는 위의 세 스레드를 소개합니다. 작업자 스레드에 대한 논의에는 javax.swing.swingworker 클래스를 사용하는 것이 포함됩니다. 이 클래스에는 작업자 스레드 작업 및 기타 스레드 작업 간의 커뮤니케이션 및 협업을 포함한 많은 유용한 기능이 있습니다.
1. 초기 스레드
각 프로그램은 응용 프로그램 논리의 시작 부분에 일련의 스레드를 생성합니다. 표준 프로그램에는 그러한 스레드가 하나뿐입니다.이 스레드는 프로그램 메인 클래스의 주요 메소드를 호출합니다. 애플릿에서, 초기 스레드는 애플릿 객체의 생성자이며, 이는 init 메소드를 호출합니다. 이러한 동작은 Java 플랫폼의 특정 구현에 따라 단일 스레드 또는 2 ~ 3 개의 다른 스레드에서 실행될 수 있습니다. 이 기사에서는이 유형의 스레드 초기 스레드를 호출합니다.
스윙 프로그램에서는 초기 스레드에서 할 일이 많지 않습니다. 가장 기본적인 작업은 GUI를 초기화하고 이벤트 디스패치 스레드에서 이벤트를 실행하는 데 사용되는 개체를 오케스트레이션하는 런닝 가능한 객체를 만드는 것입니다. GUI가 만들어지면 프로그램은 주로 GUI 이벤트에 의해 주도되며, 각각은 이벤트 디스패치 스레드에서 이벤트가 실행됩니다. 프로그램 코드는 추가 작업을 이벤트 중심 스레드 (이벤트 처리를 방해하지 않도록 신속하게 실행되면) 또는 작업자 스레드 (시간 소비 작업을 수행하는 데 사용됨)에 추가 작업을 조정할 수 있습니다.
초기 스레드 오케스트레이션 GUI 생성 작업은 javax.swing.swingutilities.invokelater 또는 javax.swing.swingutilities.invokeandwait를 호출하는 것입니다. 두 방법 모두 고유 한 매개 변수를 취합니다. runnable은 새로운 작업을 정의하는 데 사용됩니다. 그들 사이의 유일한 차이점은 : Invokerlater는 과제를 오케스트레이션하고 반환합니다. InvokeAndwait는 돌아 오기 전에 작업이 실행될 때까지 기다립니다.
다음 예를 참조하십시오.
SwingUtilities.invokelater (new Runnable ()) {public void Run () {CreateAndShowgui (); }} 애플릿에서 GUI 생성 작업은 Init Method에 넣고 invokeandwait을 사용해야합니다. 그렇지 않으면 GUI가 생성되기 전에 초기 프로세스가 가능하여 문제가 발생할 수 있습니다. 다른 경우, 오케스트레이션 GUI 제작 작업은 일반적으로 실행될 초기 스레드의 마지막 작업이므로 Invokelater 또는 Invokeandwait을 사용합니다.
초기 스레드가 GUI를 직접 생성하지 않는 이유는 무엇입니까? 스윙 구성 요소를 생성하고 상호 작용하는 데 사용되는 거의 모든 코드는 이벤트 디스패치 스레드에서 실행해야합니다. 이 제약은 아래에서 설명합니다.
2. 이벤트 배포 스레드
스윙 이벤트의 처리 코드는 이벤트 디스패치 스레드라고하는 특수 스레드에서 실행됩니다. 스윙 방법을 호출하는 대부분의 코드는이 스레드에서 실행됩니다. 대부분의 스윙 객체는 "스레드가 아닌 안전"이기 때문에 필요합니다.
코드 실행은 이벤트 디스패치 스레드에서 일련의 짧은 작업을 수행하는 것으로 생각할 수 있습니다. 대부분의 작업은 ActionListener.ActionPerformed와 같은 이벤트 처리 방법에 따라 호출됩니다. 나머지 작업은 Invokelater 또는 Invokeandwait을 사용하여 프로그램 코드에 의해 조정됩니다. 이벤트 디스패치 스레드의 작업을 빠르게 실행할 수 있어야합니다. 그렇지 않으면 처리되지 않은 이벤트가 백로그화되고 사용자 인터페이스가 "반응"이됩니다.
이벤트 디스패치 스레드에서 코드가 실행되는지 여부를 결정 해야하는 경우 javax.swing.swingutilities.iseventDispatchThread를 호출하십시오.
3. 작업자 실 및 스윙 워크 인
스윙 프로그램이 긴 작업을 수행 해야하는 경우 일반적으로 작업자 스레드를 사용하여 수행됩니다. 각 작업은 Javax.swing.swingworker 클래스의 인스턴스 인 작업자 스레드에서 실행됩니다. Swingworker 클래스는 추상 클래스입니다. 스윙 워크 객체를 만들려면 서브 클래스를 정의해야합니다. 일반적으로 익명의 내부 클래스를 사용하여이를 수행하십시오.
SwingWorker는 몇 가지 커뮤니케이션 및 제어 기능을 제공합니다.
(1) SwingWorker의 서브 클래스는 방법을 정의 할 수 있습니다. 백그라운드 작업이 완료되면 이벤트 디스패치 스레드에서 자동으로 호출됩니다.
(2) Swingworker 클래스는 java.util.concurrent.future를 구현합니다. 이 인터페이스는 배경 작업을 통해 다른 스레드에 반환 값을 제공 할 수 있습니다. 이 인터페이스의 방법은 또한 배경 작업을 취소 할 수있는 기능을 제공하고 배경 작업이 완료되었는지 또는 취소되었는지 여부를 결정합니다.
(3) 백그라운드 작업은 SwingWorker.publish를 호출하여 중간 결과를 제공 할 수 있으며 이벤트 디스패치 스레드는이 메소드를 호출합니다.
(4) 배경 작업은 결합 특성을 정의 할 수 있습니다. 바인딩 속성의 변경 사항은 이벤트를 트리거하고 이벤트 디스패치 스레드는 이벤트 핸들러를 호출하여 이러한 트리거 된 이벤트를 처리합니다.
4. 간단한 백엔드 작업
예를 들어이 작업은 매우 간단하지만 잠재적으로 시간이 많이 걸리는 작업입니다. TumbleItem Applet은 일련의 이미지 파일을 가져옵니다. 이러한 이미지 파일이 초기 스레드를 통해 가져 오면 GUI가 나타나기 전에 지연됩니다. 이러한 이미지 파일이 이벤트 디스패치 스레드에서 가져 오면 GUI가 일시적으로 응답하지 못할 수 있습니다.
이러한 문제를 해결하기 위해 TumbleItem 클래스는 초기화 될 때 StringWorker 클래스의 인스턴스를 생성하고 실행합니다. 이 객체의 doinbackground 메소드는 작업자 스레드에서 실행되고 이미지를 ImageIcon 배열로 가져오고 참조를 반환합니다. 그런 다음 완료된 메소드가 이벤트 디스패치 스레드에서 실행되고 반환 된 참조를 가져 와서 애플릿 클래스의 멤버 변수 IMG에 넣습니다. 이를 수행하면 TumbleItem 클래스가 이미지 가져 오기가 완료 될 때까지 기다릴 필요없이 즉시 GUI를 만들 수 있습니다.
다음 샘플 코드는 스윙 워크 객체를 정의하고 구현합니다.
Swingworker Worker = New Swingworker <imageicon [], void> () {@override public imageicon [] doinbackground () {final imageicon [] innerimgs = new imageicon [nimgs]; for (int i = 0; i <nimgs; i ++) {innerimgs [i] = loadimage (i+1); } 반환 내부 imgs; } @override public void done () {// "이미지로드"레이블을 제거합니다. animator.removeall (); 루프 슬롯 = -1; {imgs = get (); } catch (InterruptedException incore) {} catch (java.util.concurrent.executionException e) {문자열 왜 = null; 던질 가능한 원인 = e.getCause (); if (원인! = null) {why = ass.getMessage (); } else {gy = e.getMessage (); } system.err.println ( "파일 검색 오류 :" + why); }}}}; 스윙 워크에서 상속 된 모든 서브 클래스는 doinbackground를 구현해야합니다. 완료 방법의 구현은 선택 사항입니다.
SwingWorker는 두 개의 매개 변수를 가진 패러다임 클래스입니다. 첫 번째 유형 매개 변수는 doinbackground의 리턴 유형을 지정합니다. 또한 Get 메소드의 유형이며, 다른 스레드에서 호출하여 Doinbackground에서 반환 값을 얻을 수 있습니다. 두 번째 유형 매개 변수는 중간 결과의 유형을 지정합니다. 이 예제는 중간 결과를 반환하지 않으므로 무효로 설정됩니다.
get 메소드를 사용하여 객체 IMG (작업자 스레드에서 생성)를 참조하여 이벤트 디스패치 스레드에서 사용할 수 있습니다. 이를 통해 스레드간에 객체를 공유 할 수 있습니다.
실제로 Doinbackground 클래스에서 객체를 반환하는 두 가지 방법이 있습니다.
(1) Swingworker.get을 호출 할 매개 변수가 없습니다. 배경 작업이 완료되지 않으면 Get 메소드가 완료 될 때까지 차단됩니다.
(2) 시간 초과를 지정하려면 매개 변수가있는 Swingworker.get에 전화하십시오. 배경 작업이 완료되지 않으면 완료 될 때까지 차단하십시오 - 시간 초과가 만료되지 않는 한,이 경우 java.util.concurrent.timeoutexception을 던집니다.
5. 중간 결과를 가진 작업
작업 백엔드 작업이 중간 결과를 제공하는 것이 유용합니다. 백엔드 작업은 SwingWorker.publish 메소드를 호출하여이를 수행 할 수 있습니다. 이 메소드는 많은 매개 변수를 허용합니다. 각 매개 변수는 SwingWorker의 두 번째 유형 매개 변수로 지정된 매개 변수 여야합니다.
SwingWorker.process를 재정의하여 게시 메소드에서 제공 한 결과를 저장할 수 있습니다. 이 메소드는 이벤트 디스패치 스레드에서 호출됩니다. 게시 방법의 결과는 일반적으로 프로세스 방법으로 수집됩니다.
Filpper.java가 제공 한 예제를 살펴 보겠습니다. 이 프로그램은 백그라운드 작업을 통해 일련의 무작위 부울 테스트 java.util.random을 생성합니다. 동전 던지기 실험과 같습니다. 결과를보고하기 위해 배경 작업은 객체 Flippair를 사용합니다.
Private Static Class Flippair {Private Final Long Heads, Total; flippair (긴 머리, 총 총) {this.heads = 머리; this.total = 총; }} 헤드는 진실의 결과를 나타냅니다. 총계는 총 던지기 수를 나타냅니다.
배경 프로그램은 Filptask의 인스턴스입니다.
Private Class Fliptask는 Swingworker <Void, Flippair> {{
작업이 최종 결과를 반환하지 않기 때문에 첫 번째 유형 매개 변수가 무엇인지 지정할 필요가 없습니다. 각 "던지기"후에는 작업이 게시됩니다.
@OverRideProtected void doinbackground () {Long Heads = 0; 긴 총 = 0; 랜덤 random = new random (); while (! iscancelled ()) {Total ++; if (random.nextboolean ()) {heads ++; } 게시 (New Flippair (헤드, 총)); } return null;} 게시가 종종 호출되므로 이벤트 디스패치 스레드에 의해 프로세스 방법이 호출되기 전에 많은 flippair 값이 수집됩니다. 프로세스는 매번 반환 된 마지막 값 세트에만 초점을 맞추고이를 사용하여 GUI를 업데이트합니다.
보호 된 공극 프로세스 (목록 쌍) {flippair pair = pairs.get (pairs.size () -1); headstext.settext (String.format ( "%d", pair.heads)); TotalText.settext (String.format ( "%d", pair.total)); devText.settext (String.format ( "%. 10g", ((Double) Pair.heads)/((Double) Pair.Total) -0.5);} 6. 배경 작업을 취소하십시오
실행 배경 작업을 취소하려면 Swingworker.cancel을 전화하십시오. 작업은 자체 실행 취소 메커니즘과 일치해야합니다. 이 작업을 수행하는 두 가지 방법이 있습니다.
(1) 인터럽트가 수신되면 종료됩니다.
(2) Swingworker.iscanceled에 전화하십시오. Swingworker가 취소를 호출하면 메소드가 True를 반환합니다.
7. 속성 및 상태 방법을 바인딩합니다
SwingWorker는 바운드 특성을 지원하며 다른 스레드와 통신 할 때 매우 유용합니다. 두 가지 결합 특성을 제공합니다 : 진행과 상태. 진행 및 상태를 사용하여 이벤트 처리 스레드에서 이벤트 처리 작업을 트리거 할 수 있습니다.
속성 변경 리스너를 구현함으로써 프로그램은 진행중인 변경, 상태 또는 기타 구속력있는 특성을 포착 할 수 있습니다.
7.1 진행 경계 변수
진행 상황 바인딩 변수는 0 ~ 100 범위의 정수 변수입니다. Setter (Protected Swingworker.setProgress) 및 Getter (Public Swingworker.getProgress) 메소드를 사전 정의했습니다.
7.2 상태 바운드 변수
상태 바인딩 변수의 변화는 수명주기 동안 스윙 워크 객체를 변경하는 과정을 반영합니다. 이 변수에는 열거 유형의 Swingworker.stateValue가 포함됩니다. 가능한 값은 다음과 같습니다.
(1) 보류 중
이 상태는 Doinbackground 방법이 호출된다는 것을 물체의 생성에서 알 수있는 한동안 지속됩니다.
(2) 시작
이 상태는 doinbackground 메소드가 호출 될 때까지 호출되기 전에 잠시 지속됩니다.
(3) 완료
객체가 존재하는 나머지 시간은이 상태에 남아 있습니다.
현재 상태의 값을 반환 해야하는 경우 SwingWorker.getState에 전화 할 수 있습니다.
7.3Status 방법
향후 인터페이스에서 제공하는 두 가지 방법은 배경 작업의 상태를보고 할 수 있습니다. 작업이 취소되면 iscancelled는 true를 반환합니다. 또한 작업이 완료되면, 즉 정상적으로 완료되거나 취소되면 ISDONE은 TRUE를 반환합니다.
최상위 컨테이너를 사용합니다
Swing은 JFrame, JDialog, Japplet의 3 가지 최상위 컨테이너 클래스를 제공합니다. 이 세 클래스를 사용할 때는 다음 사항에주의를 기울여야합니다.
(1). 화면에 표시 되려면 각 GUI 구성 요소는 포함 계층의 일부 여야합니다. 포함 계층은 구성 요소의 트리 구조이며, 최상위 컨테이너는 루트입니다.
(2). 각 GUI 구성 요소는 한 번만 포함될 수 있습니다. 구성 요소가 이미 컨테이너에있는 다음 새 컨테이너에 추가하려고 시도하면 구성 요소가 첫 번째 컨테이너에서 제거되어 두 번째 컨테이너에 추가됩니다.
(3). 각 최상위 컨테이너에는 컨텐츠 창이 있습니다. 일반적 으로이 컨텐츠 패널에는 최상위 컨테이너 GUI의 모든 시각적 구성 요소가 직접 또는 간접적으로 포함됩니다.
(4). 상단 컨테이너에 메뉴 표시 줄을 추가 할 수 있습니다. 일반적 으로이 메뉴 막대는 상단 컨테이너이지만 콘텐츠 패널 외부에 배치됩니다.
1. 최상위 컨테이너 및 포함 계층
스윙 구성 요소를 사용하는 각 프로그램에는 하나 이상의 최상위 컨테이너가 있습니다. 이 최상위 컨테이너는 계층 구조를 포함하는 루트 노드입니다.이 계층은이 최상위 컨테이너에 나타날 모든 스윙 구성 요소를 포함합니다.
일반적으로 별도의 스윙 GUI 기반 애플리케이션에는 하나 이상의 포함 계층이 있으며 루트 노드는 JFrame입니다. 예를 들어, 응용 프로그램에 1 개의 창과 2 개의 대화 상자가있는 경우 응용 프로그램에는 3 개의 포함 수준이 있습니다. 즉, 3 개의 최상위 컨테이너가 있습니다. 격리 계층 구조는 JFrame을 루트 노드로 취하며, 두 개의 다른 격리 계층은 각각 jDialog를 루트 노드로 가지고 있습니다.
스윙 구성 요소를 기반으로 한 애플릿에는 적어도 하나의 포함 계층이 포함되어 있으며, 그 중 하나는 japplet을 루트 노드로 만들어야한다는 것을 결정할 수 있습니다. 예를 들어, 대화 상자가있는 애플릿으로 두 개의 포함 수준이 있습니다. 브라우저 창의 구성 요소는 격리 계층 구조에 배치되며 루트 노드는 Japplet 객체입니다. 대화 상자에는 계층이 포함되어 있고 루트 노드는 jdialog 객체입니다.
2. 컨텐츠 패널에 구성 요소를 추가하십시오
다음 코드 작업은 위의 예에서 프레임의 컨텐츠 패널을 가져 와서 노란색 레이블을 추가하는 것입니다.
frame.getContentPane (). Add (YellowLabel, BorderLayout.Center);
코드에 표시된대로 먼저 최상위 컨테이너의 컨텐츠 패널을 찾아 GetContentPane 메소드를 통해 구현해야합니다. 기본 컨텐츠 패널은 간단한 중간 컨테이너로, PANITHLAYOUT을 패널 관리자로 사용하여 JComponent의 상속입니다.
컨텐츠 패널 사용자 정의는 간단합니다. 패널 관리자를 설정하거나 국경을 추가하십시오. getContentPane 메소드는 jcomponent 객체가 아닌 컨테이너 객체를 반환한다는 점에 유의해야합니다. 즉, Jcomponent의 기능 중 일부를 활용 해야하는 경우 리턴 값을 변환하거나 컨텐츠 패널로 자신의 구성 요소를 만들어야합니다. 이 예제는 일반적으로 두 번째 방법을 사용합니다. 두 번째 방법은 명확하고 명확하기 때문입니다. 때때로 사용하는 또 다른 방법은 컨텐츠 패널에 자체 정의 구성 요소를 추가하여 콘텐츠 패널을 완전히 덮는 것입니다.
나만의 콘텐츠 패널을 만들면 불투명한지 조심하십시오. 불투명 한 jpanel이 좋은 선택이 될 것입니다. 기본적으로 JPANEL의 레이아웃은 FlowLayout으로 관리되며 다른 레이아웃 관리자로 교체 할 수 있습니다.
구성 요소가 컨텐츠 패널이 되려면 최상위 컨테이너의 SetContentPane 메소드를 사용해야합니다.
// 패널 생성 및 IT.jpanel contentpane = new jpanel (new BorderLayout ()); contentpane.setborder (someborder); contentpane.add (somecomponent, borderlayout.center); contentpane.add (onthercomponent, borderlayout.page_end); Pane.//contentpane.setopaque(true); TopleVelContainer.SetContentPane (ContentPane);
참고 : 투명 컨테이너를 JSCrollpane, JSPlitpane 및 Jtabbedpane과 같은 컨텐츠 패널로 사용하지 마십시오. 투명한 컨텐츠 패널은 구성 요소가 혼란스러워집니다. setopaque (True) 방법을 통해 투명한 스윙 구성 요소를 불투명하게 만들 수는 있지만 일부 구성 요소가 완전히 불투명 해지면 제대로 보이지 않습니다. 예를 들어 태그 패널입니다.
3. 메뉴 표시 줄 추가
이론적으로 각 최상위 컨테이너에는 메뉴 표시 줄이있을 수 있습니다. 그러나 사실은 메뉴 표시 줄이 프레임이나 애플릿에만 나타납니다. 최상위 컨테이너에 메뉴 표시 줄을 추가하려면 jmenubar 객체를 만들고 메뉴를 조립 한 다음 setjmenubar 메소드를 호출해야합니다. ToplevelDemo 인스턴스는 다음 코드를 통해 메뉴 표시 줄을 프레임에 추가합니다.
frame.setjmenubar (Cyanmenubar);
4. 루트 창
각 최상위 컨테이너는 루트 컨테이너라고 불리는 암시 적 중간 컨테이너에 의존합니다. 이 루트 컨테이너는 컨텐츠 패널 및 메뉴 표시 줄과 두 개 이상의 다른 컨테이너를 관리합니다 (레이어 파인 등 참조). 일반적으로 스윙 구성 요소 루트 컨테이너 사용에 대해 알 필요가 없습니다. 그러나 마우스를 가로 채려면 여러 구성 요소를 클릭하거나 그리기하려면 루트 컨테이너를 알아야합니다.
위의 내용은 컨텐츠 패널과 선택적 메뉴 표시 줄에 대해 설명되었으며 여기에서는 반복되지 않습니다. 루트 컨테이너에 포함 된 다른 두 구성 요소는 레이아웃 패널과 유리 패널입니다. 레이아웃 패널에는 메뉴 패널과 컨텐츠 패널이 직접 포함되어 있으며 Z 좌표로 추가 된 다른 구성 요소를 정렬 할 수 있습니다. 유리 패널은 일반적으로 상단 레이어에서 발생하는 입력 동작을 가로 채고 여러 구성 요소를 그리는 데 사용될 수 있습니다.