2009-09-15 3 views
6

지난 몇 년 동안 저는 주로 스레드 접근 측면에서 매우 보수적 인 Eclipse 개발을했습니다 : UI 위젯 (예 : 색상, 텍스트)에서 UI 위젯의 속성을 변경하려는 시도는 throw합니다. 예외.스윙의 스레딩 정책을 위반하면 어떻게됩니까?

많은 수의 사용자 정의 위젯이있는 윈도우가있는 기존의 Swing 프로그램을보고 있습니다. 이 위젯 각각에 대해 돌연변이 함수를 실행하는 별도의 스레드가 있으며 돌연변이 함수는 레이블 색상 및 값과 같은 일부 값을 읽고 일부를 작성합니다 (예 : 배경색 변경). 커스텀 페인팅이나 그와 비슷한 것들이 없다는 점에 주목하십시오. 그 중 일부는 대부분 JLabel 인 하위 위젯에 대한 변경 사항 일뿐입니다.

현재 이것은 별도의 스레드에서 실행되며 Swing 이벤트 스레드에서는 실행되지 않습니다. 이 스레드는 400 개의 위젯을 모두 처리하고 각각의 위젯을 호출합니다. 업데이트가 제대로 작동하는 것 같지만 GUI가 사용자 입력에 응답하지 않습니다.

Swing 스레드 외부에서 약 0.4msec 동안 실행되는 모든 것을 취해서 invokeLater 또는 invokeAndWait의 모든 호출을 뮤 테이타로 랩핑하면 UI가 훨씬 더 반응적입니다.

내가 이해하려고 노력 중이 야입니다 :

1) 가끔 합법적 인 스윙 스레드 외부에서 모든 통화를 할 수 있나요?

2) 외부에서 호출 할 때 스윙 스레드에 미치는 영향 및 UI의 응답 성이 떨어지는 이유는 무엇입니까?

답변

3

"Nothing"에서 간헐적 인 문제까지 "모든 것이 망가졌습니다. GUI에서 모두 작업하십시오!"

주된 (가장 명백한) 시각 효과는 GUI 스레드 (누군가가 단추를 누르고 절전 (5000) 등)를 수행하는 경우 GUI가 다시 칠하지 않는다는 것입니다. 그것은 당신에게 전달할 수있는 유일한 스레드를 잡고 있기 때문에 불가능합니다! 이것은 사람들로 하여금 Java가 정말로 느리다 고 생각하게 만듭니다. 그것은 나쁘지는 않지만, 이와 같은 연구 관행을 귀찮게하지 않는 많은 사람들이 선적 제품을 생산했다고 쉽게 프로그램 할 수 있습니다.

다음으로 큰 문제는 다른 스레드 (예 : 주 스레드로 전달 된 스레드)에서 화면을 그릴 때 이상한 동작이 발생할 수 있다는 것입니다. 스윙은 이미 프레임을 렌더링하는 방법에 대해 너무 까다 롭습니다 - 스레딩을 변수로 가져옵니다!

마지막으로 드물게 (또는 종종 잘못된 스레드에서 꽉 짜낸 루프에서 스윙 구성 요소를 호출하는 경우) 스레드 충돌이 발생할 수 있습니다. 예외가 발생하거나 예외가 발생하거나 잘못 렌더링 될 수 있지만 명확하지 않을 수 있습니다.

1

기본적으로 스레드로부터 안전하지 않은 개체는 다중 스레드 방식으로 실행됩니다. HashMap을 읽는 것만 큼 단순한 무언가라도 무한 루프에 걸릴 수 있습니다. AWT가 잠금을 사용하기 때문에 (나쁘게) 교착 상태가 발생할 수도 있습니다. 그러나 업데이트 된 버전의 Java가 갑자기 일부 고객 시스템에서 문제를 일으킬 수는 있겠지만 사용자는이를 피할 수 있습니다.

(BTW :. 그것은 AWT 이벤트 발송 쓰레드의,의 스윙하지 않음)에 대한

1

를 (1) 화면에 픽셀이 Event Dispatching Thread (EDT)에서 호출해야 업데이트 엄지 손가락 아무것도 원칙적으로. 일부 JVM이 EDT 외부에서 업데이트를 처리 할 수있는 곳에서는 절대로이 작업에 의존해서는 안되며 일부 컴퓨터와 다른 모양과 느낌이 허용되지 않을 수 있습니다. 동작은 정의되지 않았으며 이는 사용자가 보지 못한 응답성에 대한 설명입니다.

3

1) 스윙 스레드 외부에서 이러한 모든 호출을하는 것이 때때로 합법적 일 수 있습니까?

예를 들어 텍스트 필드의 텍스트 값을 설정하면 자동 EDT 프록 싱이 있지만 예외는 있지만 이 없으며 상황이 더 나은 경우가 있습니다. 많은 업데이트를 수행하는 경우 개별 호출 대신 단일 EDT 호출 (invokeLater())에 대한 단일 호출만으로 모든 작업을 수행 할 수 있습니다. 그러나 이러한 일괄 처리조차도 거의 도움이되지 않습니다. 길고 짧음 : EDT에서 Swing 구성 요소에 대한 연산을 수행합니다. 여기에는 읽기 및 쓰기가 포함됩니다.

2) 외부에서 호출 할 때 스윙 스레드에 미치는 영향 및 UI의 응답 성이 떨어지는 이유는 무엇입니까?

글쎄, EDT는 GUI 업데이트를 담당합니다. 외부에서 전화를 걸면 '덜 반응합니다'라는 뜻이 아닙니다. 사용자 인터페이스를 업데이트하는 실제 낮은 수준의 시스템 호출이 전혀 발생하지 않는다는 것입니다. 앱에서 실제로 발생하는 현상은 원래 개발자가 정말 불쾌한 경쟁 조건을 만들지 않고도 스윙 구성 요소에서 운 좋은 상태를 변화시키고 있다는 것입니다. 그런 다음 다른 일부 이벤트로 인해 EDT에서 다시 칠하기가 발생하여 구성 요소가 업데이트됩니다. 이것은 '응답 성 부족'인 것처럼 보일 수 있습니다. 그러나 실제로 일어나고있는 것은 '화면 새로 고침 부족'입니다.

EDT는 일반적인 스레드 일 뿐이지 만 GUI 관련 신호 (예 : 명령 그리기)를 처리하는 긴밀한 루프에서 실행된다는 점에서 약간 특이합니다. EDT에서 이러한 유형의 명령을 게시하는 semantec은 실제로 우리가 Java 스레드 (메시지 펌프에 작업을 제출하는 것과 관련됨)로 생각하는 것과는 정말로 다릅니다.

길고 짧음 - EDT의 Swing 객체와 만 상호 작용한다고 말하는 모든 Javadoc은 이유가 있기 때문에 작성되었습니다. 그것을 망쳐 놓지 마십시오. 백그라운드 처리를하고 싶다면 J * 구성 요소와의 상호 작용을 EDT로 다시 프록시 할 책임이 있습니다 (가장 일반적으로 invokeLater() 사용).

2
  1. 실제로 예외는 없습니다. Kevin은 부분적으로 정확합니다. JTextComponent.setText()는 스레드로부터 안전하다고 광고됩니다. 그러나 1.6 코드를 보면 문서 개체에 동기화 기능을 제공하며 EDT는 사용하지 않습니다. 다른 스윙 구성 요소 (또는 스윙 구성 요소를 제어하는 ​​무언가)가 문서 객체를 수신하지 않는 한 괜찮습니다. 자신에 대한 걱정을 덜어 주시고 항상 EDT를 사용하십시오. Kevin이 말했듯이, 달리 할 수있는 상황은 없습니다.

  2. 코드를 파고 들지 않고 말하기는 힘들다. 동작은 정의되지 않습니다. 백그라운드 작업이 오래 실행 되었다면 (> 몇 초) 반대 효과가 나타납니다. EDT를 사용하면 작업이 실행되는 동안 UI가 응답하지 않게됩니다.

다행히도, 다행히도, 올바른 방법은 어쨌든 최선의 방법이라고 생각합니다. :)

썬은 실현되지 않은 구성 요소와 다른 스레드를 사용하는 것이 괜찮다고 말을 사용하지만, 나중에 철회 :

Related stackoverflow question

체크 아웃 일의 UI 튜토리얼을 스윙과 동시성 (I에 링크를 게시,하지만이 stackoverflow0 내 첫 번째 대답입니다.