>  기사  >  Java  >  Java를 처음 배우는 초보자를 위한 메모 (8)

Java를 처음 배우는 초보자를 위한 메모 (8)

黄舟
黄舟원래의
2016-12-20 13:54:131177검색

22일 제 노트에 질문이 없었나요? 왜 컴파일한 프로그램에 비동기화가 없나요? csdn에 보냈습니다. 이제 이 문제는 기본적으로 해결되었습니다.

답변자: bluesmile979 (웃음) ( ) 평판: 100 2003-01-22 21:08:00 점수: 0
제 생각을 말씀드리자면 가장 큰 문제는 멀티스레딩에 관한 것 같아요. 코드를 읽어보니 두 줄밖에 없는 것 같습니다. 이 예에서는 더 많은 스레드가 있어야 합니다. 여러 스레드가 시간 분할을 놓고 경쟁하는 경우 당연히 중단될 가능성이 훨씬 커집니다. 루프를 추가하더라도 머신의 컴퓨팅 속도로 인해 다중 스레드 간의 경쟁만큼 명확하지는 않습니다. 나는 당신이 어떻게 생각하는지 모르겠어요.

응답자: xm4014(forrest) ( ) 평판: 100 2003-01-22 22:07:00 점수: 0
bluesmile979에게 (웃음)
나도 그런 생각을 해본 적이 있기 때문이다. of 스레드가 너무 적어서 발생하는 문제인데 Think in Java 루틴의 두 매개변수를 모두 1로 설정하여 실행해 보니 결국 제가 작성한 프로그램과 동일하고 스레드가 2개뿐이고 결과는 여전합니다. out of sync. 이것을 어떻게 설명하나요?

답글: tianfeichen (잘 들어보세요) ( ) 평판: 110 2003-01-22 23:57:00 점수: 0
스레드 배열은 결국 무작위이며 드물게 발생합니다. 비동기 현상이 발생하지만 빈도가 작으면 감지하기가 쉽지 않습니다.
나의 일반적인 방법은 루프 중에 출력을 요구하지 않고 먼저 무한 루프를 시작하는 것입니다.
if (counter1 != counter2)
{
시스템 .out.PRintln(counter1 + " ," + counter2)
System.exit(0);
}
나머지는 기다리는 것입니다. 일반적으로 결과는 12초 또는 몇 초 안에 확인할 수 있습니다. 초 , 개수가 수십만 또는 수백만에 도달한 것을 확인할 수 있습니다.
5개의 스레드가 동시에 열리고 1분 정도 기다리면 동기화된 것으로 간주합니다.

제 방법이 과학적이진 않을지 몰라도 효과는 꽤 좋습니다.

응답자: xm4014(forrest) ( ) 평판: 100 2003-01-23 11:44:00 점수: 0
디버그하는 데 도움을 주실 수 있나요? 당신의 방법을 따르면 왜 결과가 나오지 않습니까?
다음 코드를 직접 복사하면 됩니다. 프로그램 이름은 Sharing2.java이고 버전은 1.4.1입니다.
class TwoCounter extends Thread {
private int count1 = 0, count2 = 0;
private boolean start=false;
public void start(){
if (!started)
{
started=true;
super.start();
}
}
public void run() {
while (true) {
count1++;
count2++;
// System.out.println("Count1="+count1+",Count2="+ count2 );
try {
sleep(500);
} catch (InterruptedException e){System.out.println("TwoCounter.run");}
}
}

public void synchTest() {
// Sharing2.incrementaccess();
if(count1 != count2)
{System.out.println(count1+","+count2);
System.exit(0);
}
}
}

class Watcher는 Thread {
private Sharing2 p;
public Watcher(Sharing2 p) { this.p = p;
start();
}
public void run() {
while(true) {
p.s.synchTest();
try {
sleep(500);
} catch(InterruptedException e){System.out.println("Watcher.run");}
}
}
}

공개 클래스 Sharing2 {
TwoCounter s;
private static int accessCount = 0;
public static void incrementAccess() {
// accessCount++;
// System.out.println("accessCount= " +accessCount);
}
public static void main(String[] args) {
Sharing2 aaa = new Sharing2();
aaa.s=new TwoCounter();
aaa . s.start();
new Watcher(aaa);
}
} ///:~

그리고 당신 말에 따르면 내 프로그램에는 문제가 없다고 하는데, 단지 스레드 수가 적고 비동기화를 일으키기 어렵다는 것뿐입니다. 카운터가 크게 증가해야 가능합니다.

답글: hey_you(Hey) ( ) 평판: 100 2003-01-23 13:27:00 점수: 0

제 생각에는 동기화 부족으로 인한 갈등은 가능성이 있으며 동기화는 이 가능성을 0으로 만듭니다. 비동기화를 발견하지 못했다고 해서 비동기화가 절대 발생하지 않는다는 것을 증명할 수는 없습니다. 이는 단지 시간 문제일 뿐입니다. 시스템의 스레드 스케줄링은 환경의 영향을 받습니다. 컴퓨터에서 동시에 실행되는 프로그램이 많으면 상황이 다를 수 있습니다.

응답자: xm4014(forrest) ( ) 평판: 100 2003-01-23 15:56:00 점수: 0
ㅋㅋㅋ tianfeichen(잘 들어보세요) 방식으로 프로그램을 실행했는데, 위에 게시한 코드는 실제로 counter1 = 217327, counter2 = 217356이라는 결과를 생성했는데 이는 상당히 다릅니다. 하지만 그 시간은 결코 1~2분처럼 간단하지 않습니다. 적어도 2시간은 저와 그 사람의 작업 환경의 차이 때문일 수 있습니다.

더 이상 논의할 필요가 없다고 생각하시면 다른 분들이 더 많은 의견을 주셨으면 좋겠습니다.

답글: bluesmile979 (웃음) 평판: 100 2003-01-23 16:38:00 점수: 0
시험을 봐서 한두 시간 정도는 버틸 수 있을 거라 확신합니다.

문제의 결과는 단 2점이라고 봅니다. 하나는 제가 생각하는 스레드 수

다른 하나는 setText가 더 많은 처리를 수행하고 더 많은 리소스를 차지할 것이라고 생각하는 것입니다.

두 상황 모두 이 문제의 가능성에 영향을 미칠 것입니다. :) 요약해 보겠습니다. 하하.

응답자: linliangyi(블루 마운틴 커피) ( ) 평판: 100 2003-01-23 17:10:00 점수: 0
수면(500)은 (5000) 시간보다 더 많은 시간이 소요됩니다. 따라서 스레드가 절전 모드에서 전환될 확률은 중단될 확률보다 훨씬 좋습니다! ! (내 프로그램을 다시 보면 알 수 있습니다)

사실 두 변수가 같지 않음에서 같음으로 변경됩니다. 이는 동기화되지 않음을 의미합니다! !

그런데 setText와 같은 스레드에서 Swing 및 awt 컨트롤이 작동하면 많은 사고가 발생하는 경우가 많습니다
원본 포스터에서 관련 서적을 읽을 수 있습니다! !

응답자: xm4014(forrest) ( ) 평판: 100 2003-01-24 14:25:00 점수: 0
여러분의 의견을 함께 정리하겠습니다:

가장 먼저 해야 할 일은 동기화 방법이나 동기화 블록을 정의하기 위해 동기화된 키워드를 사용하지 않으면 비동기화 가능성이 확실히 존재하는 반면에 동기화됨은 이 가능성을 0으로 만듭니다.

첫 번째 경우, 비동기화 가능성이 존재하더라도 그 확률은 다음 요소의 영향을 받습니다
1. 서로 다른 운영 체제 및 운영 환경에서 비동기화를 캡처합니다. 확률은 다를 수도 있고, 대기 시간이 길어지거나 짧아질 수도 있습니다. 🎜> 2. 프로그램의 스레드 수가 너무 적으면 이러한 비동기화를 포착하기 어렵고 시간이 오래 걸릴 수 있습니다
3. 예를 들어 awt 클래스에서 GUI 관련 메서드를 사용하면 더 많은 리소스를 차지할 수 있고 많은 사고가 발생할 수 있으므로 충돌 가능성이 훨씬 더 큽니다
4. 스레드는 운영 체제에 의해 무작위로 할당됩니다. 이 불확실성은 최종 결과에도 영향을 미칠 것입니다

그것이 맞는지 모르겠습니다.
내일 공식적으로 결론이 납니다

하지만 솔직히 말해서요. , 최종 결과인 counter1(217327)과 counter2(217356)이 왜 그렇게 다른지 이해가 되지 않습니다. 감지된 두 카운터 사이의 개수는 최대 1개입니다. 이러한 큰 차이는 특정 카운터의 자체 증가 문이 전혀 실행되지 않고 여러 번 실행되었기 때문에 발생할 수 있습니다. 너무 무섭습니다! 다른 스레드가 존재하면 현재 스레드가 실행되는 것을 중단하지는 않습니다. 대부분은 기다렸다가 실행됩니다. 괜찮으시다면 설명 부탁드립니다.

결과적으로 지금은 새로운 질문이 있어서 답변을 얻으려면 기다려야 할 것 같습니다.

하지만 오늘은 동기화와 관련된 또 다른 문제를 해결할 수 있습니다. 포럼에서 본 게시물입니다. 문제를 해결할 수 없기 때문에 돌아가서 스레드와 동기화를 공부해야 한다고 생각합니다.
질문은 다음과 같습니다.

file:// 이 프로그램을 동기화, wait(), 알림을 중심으로 분석해서 설명해주세요.
class ThreadA
{
public static void main(String[] args)
{
ThreadB b=new ThreadB();
b.start();
시스템 .out.println("b는 시작입니다....");
synchronized(b)//괄호 안의 b는 무엇을 의미하며 어떤 역할을 합니까?
{
시도해 보세요
{
System.out.println("b가 완료되기를 기다리는 중...");
b.wait();//이 문장의 의미는 무엇이며 누가 기다려야 합니까?
System.out .println("완료되었습니다. 이제 메인 스레드로 돌아갑니다");
}catch(InterruptedException e){}
}
System.out.println("총계는 :"+b.total);
}
}

class ThreadB 확장 Thread
{
int total;
public void run()
{
synchronized(this)
{
System.out.println("ThreadB가 실행 중입니다..");
for (int i=0;i<100;i++ )
{
total +=i;
시스템 .out .println("total is "+total);
}
notify();
}
}
}

이 프로그램을 분석하려면 먼저 다음을 수행해야 합니다. 통지( ) 및 wait()를 이해하십시오. 며칠 전에 스레드를 기록할 때 이 두 메소드가 기록되지 않은 이유는 이 두 메소드가 원래 Thread 클래스에 속하지 않고 다른 클래스에서는 가장 낮은 수준의 객체 기본 클래스에 속하기 때문입니다. 즉, Thread만이 아닙니다. 모든 객체에는 알림 및 대기 기능이 있습니다. 왜일까요? 잠금을 조작하는 데 사용되며 모든 객체에는 잠금이 있습니다. 잠금은 기본이므로 잠금을 조작하는 방법도 가장 기본입니다. 더 자세히 읽으려면 Think in Java 14.3.1의 3부: 대기 및 알림, 즉 wait() 및 알림을 검토하는 것이 가장 좋습니다.

Think in Java의 설명을 따르세요. "wait()를 사용하면 조건이 변경될 때까지 "적극적으로" 기다리는 동안 스레드를 "휴면" 상태로 설정하고, inform() 또는 informAll()이 변경될 때만 스레드가 활성화되어 조건이 변경되었는지 확인합니다."

이 문장을 설명해 보겠습니다.
"wait()를 사용하면 스레드를 "sleep" 상태로 전환할 수 있습니다. 즉, wait는 현재 스레드도 차단합니다. 이는 sleep 또는 동일합니다. 정지와 정지의 차이점은 무엇인가요?

차이점은 "(대기) 동시에 조건이 변경될 때까지 "적극적으로" 대기한다는 것입니다. 이는 스레드 간의 충돌을 방지하기 위해 때때로 동기화(동기화)의 도움이 필요하기 때문에 이를 수행할 수 없습니다. 즉, 개체 잠금을 획득해야 합니다. 개체 잠금을 사용하려는 다른 스레드는 동기화 메서드 또는 동기화 블록의 모든 프로그램이 실행될 때까지만 대기할 수 있습니다. 동기화 방법, 동기화된 블록에서는 sleep()이나 suspens() 모두 호출 시 잠금을 해제할 수 없습니다.
그러나 대기는 동기화 방법을 만들 수 있습니다. 동기화 블록은 일시적으로 개체 잠금을 포기하고 개체 잠금이 필요한 다른 사람에게 일시적으로 제공합니다(여기서는 프로그램 블록 또는 스레드여야 함). 이는 실행 중에 스레드 개체의 다른 동기화 메서드를 호출할 수 있음을 의미합니다. wait()! 다른 상황에서는 불가능합니다.
하지만 앞서 말한 내용에 주의하세요. 저는 객체 잠금을 임시로 포기하고 다른 스레드에 임시로 사용합니다. 아직 이 개체를 사용해야 합니다. 잠금 장치가 회수되었습니다. 무엇을 기다려야 할까요? 잠시 기다렸다가 다른 사람이 해당 개체를 사용한 후에 다시 돌려주세요.
그럼 객체 잠금을 다시 가져오는 방법은 무엇인가요?
첫 번째 방법은 대여 시간을 제한하는 것입니다. wait(1000)과 같은 매개변수를 밀리초 단위로 설정합니다. 즉, 빌려주기만 한다는 의미입니다. 1초 동안 꺼냈다가 1초 후에 자동으로 돌려받습니다.
두 번째 방법은 빌려준 사람에게 다 썼다고 돌려달라고 요청하는 것입니다. 이번에는 바로 가져가겠습니다. .. 내가 1시간 설정하고 가져가는데 다른 사람이 30분만 걸려서 끝내면 어떡하지? , 아무리 오래 설정해도 다른 사람은 어떻게 알림을 받나요? 다들 알 수 있을 거라 생각합니다. 알림()은 마지막 문장의 의미입니다. ) 또는 informAll()이 변경되면 스레드가 활성화됩니다." .
따라서 해당 클래스에 스레드 관련 처리가 준비되어 있는지 여부에 관계없이 동기화된 메소드 또는 동기화된 블록 내에 wait() 및 inform()을 배치할 수 있습니다. . 그리고 실제로는 동기화된 메소드나 동기화된 블록에서만 wait() 및 통지()를 호출할 수 있습니다.

이때 위 프로그램을 설명하면 쉽습니다.

동기화(b){...}; 동기화된 블록을 정의하고 b를 리소스 잠금으로 사용하는 것을 의미합니다. b.wait(); 동일한 잠금을 사용하는 다른 스레드가 실행할 기회를 갖도록 잠금을 일시적으로 해제하고 현재 스레드를 차단하는 것을 의미합니다. 그 이후에는 wait가 있는 스레드에 lock이 다 사용되었음을 알리기 위해 inform()을 사용한다. 계속 실행하세요.

위 내용은 Java를 처음 배우는 분들을 위한 메모입니다. (8) 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.