이 기사는 주로 Java 동시성 조건 차단 조건의 응용 프로그램 샘플 코드를 다음과 같이 연구합니다.
조건은 객체 모니터 방법 (대기, 알림 및 알림)을 완전히 다른 객체로 분해하여 이러한 객체를 잠금 구현과 결합하여 각 객체는 여러 대기 세트 (대기 세트)를 제공합니다. 그중에서도 Lock은 동기화 된 메소드 및 명령문의 사용을 대체하며 조건은 객체 모니터 방법의 사용을 대체합니다.
조건은 대기, 알림 및 기타 방법을 대체하는 데 사용될 수 있으므로 이전에 작성된 스레드 간 커뮤니케이션 코드를 비교하고 원래 문제를 살펴볼 수 있습니다.
두 개의 스레드가 있습니다. 자식 스레드는 먼저 10 번 실행 한 다음 기본 스레드가 5 번 실행 된 다음 하위 스레드로 전환 한 다음 메인 스레드가 5 번 실행됩니다 ...이 왕복 여행은 50 회입니다.
나는 대기를 사용하여 이전에 구현하기 위해 통지했지만 이제 조건을 다시 작성하기 위해 조건을 사용하고 코드는 다음과 같습니다.
public class conditioncommunication {public static void main (string [] args) {비즈니스 비즈니스 = new Business (); new Thread (new Runnable () {// 어린이 스레드 @override public void run () {for (int i = 1; i <= 50; i ++) {bussiness.sub (i); 50; i ++) {bussiness.main (i);}}}} 클래스 비즈니스 {lock lock = new reentrantlock (); 조건 = lock.newcondition (); {condition.await (); // 조건을 사용하여 조건을 사용하여} catch (예외 e) {// todo auto-auto-auto-auto-auto-auto-recke.printstacktrace (in j = 1; j <= 10; j ++) {system.out.println ( " + j +"의 서브 스레드 시퀀스 "} bsh}; false; rest. blocke.printstacktrace ();}} for (int j = 1; j <= 10; j ++) {System.out.println ( " + j +"의 메인 스레드 순서, " + i);} bshouldSub = true; 조건.코드 관점에서 조건은 잠금과 함께 사용됩니다. 잠금 장치가 없으면 조건이 잠금을 통해 생성되기 때문에 조건을 사용할 수 없습니다. 이 사용법은 매우 간단합니다. 동기화, 대기 및 알림의 사용을 마스터하는 한 잠금 및 조건의 사용을 완전히 마스터 할 수 있습니다.
위의 내용은 동기화 된 및 객체 모니터 방법 대신 잠금 및 조건을 사용하여 두 스레드 간의 통신을 실현합니다. 이제 약간 더 고급 응용 프로그램을 작성해 봅시다. 버퍼의 차단 대기열을 시뮬레이션하십시오.
버퍼 란 무엇입니까? 예를 들어, 지금 메시지를 보내고 싶은 많은 사람들이 있습니다. 나는 대중 교통 역이며 다른 사람들이 메시지를 보내도록 돕고 싶습니다. 이제 두 가지 일을해야합니다. 한 가지는 사용자가 보낸 메시지를 수신하여 버퍼에 순서대로 넣는 것입니다. 다른 것은 버퍼에서 순서대로 사용자가 보낸 메시지를 꺼내서 보내는 것입니다.
이제이 실제 문제를 추상화하십시오. 버퍼는 배열입니다. 배열에 데이터를 작성하거나 배열에서 데이터를 꺼낼 수 있습니다. 내가해야 할 두 가지 일은 데이터를 저장하고 다른 하나는 데이터를 얻기 위해 두 개의 스레드를 시작하는 것입니다. 그러나 문제는 버퍼가 가득 차면 수신 된 메시지가 너무 많다는 것을 의미합니다. 즉, 전송 된 메시지가 너무 빠르고 내 인생의 다른 스레드가 보내기에 충분하지 않아 버퍼가 빠지지 않으므로 데이터 스토리지 스레드를 차단하고 기다려야한다는 것입니다. 반대로, 너무 빨리 전달하고 이제 버퍼의 모든 내용이 나에 의해 전송되고 사용자가 새 메시지를 전송하지 않았 으면 현재 데이터 수집 스레드를 차단해야합니다.
자,이 버퍼의 차단 큐를 분석 한 후 조건 기술을 사용하여 구현하겠습니다.
클래스 버퍼 {Final Lock Lock = new ReintrantLock (); // 잠금 조건을 정의합니다. 최종 조건을 정의하지 않음 NoteFull = lock.newcondition (); // 조건증 조건 정의 notempty = lock.newcondition (); itedsipine extentfinal 객체 [] items = new Object [10]; // 다음 시뮬레이션에 대해 10]을 설정하지 않음, 대단한 itpt, 크기를 설정하지 않습니다. count; // 배열 위트 스크립트는 큐 공개 공개 void put (object x) 던지기에 대한 위치를 교정하는 데 사용됩니다. BET! "); notefull.await (); // 큐가 가득 차면 데이터 저장 실을 차단하고 깨어나기를 기다리고 있습니다} // 항목이 가득 차 있지 않으면 [putptr] = x; if (++ putptr == items.length) // 배열 끝에 도달하는 판단입니다. 도달하면 시작 putptr = 0; ++ count; // 메시지 system.out.println 수 (thread.currentThread (). getName () + "value :" + x); notempty.signal (); // 이제 queue에 데이터가 있습니다. 빈 큐가있는 스레드를 깨우면 데이터를 얻을 수 있습니다} 마지막으로 {lock.unlock (); // 잠금을 다운로드}} // 큐 공개 객체에서 데이터를 가져 오십시오 () take ()가 인터럽트 exception {lock.lock (); 시간이 지남에 따라! "); notempty.await (); // 큐가 비어 있으면 큐가 비어 있으면 스레드가 스레드를 검색하기 위해 데이터를 차단하고, 깨어나기를 기다리고있다} // 객체 x = 항목 [takeptr]; System.out.println (thread.currentthread (). getName () + "값을 꺼냅니다 :" + x); notefull.signal (); // 이제 큐에 위치가 있습니다. 대기열로 가득 찬 실을 깨우면 데이터를 저장할 수 있습니다. return x;} 마지막으로 {lock.unlock (); // lock}}}이 프로그램은 고전적이며 공식 JDK 문서에서 꺼내어 의견을 추가했습니다. 이 프로그램에는 정의 된 두 가지 조건이 있으며, 이는 두 스레드를 실행하고 각각 대기하고 일어나기 위해 사용됩니다. 아이디어는 명확하고 프로그램도 매우 강력합니다. 한 가지 질문을 고려할 수 있습니다. 왜 두 코드를 사용해야합니까? 이 디자인의 이유가 있어야합니다. 조건을 사용하는 경우 이제 대기열이 가득 차 있다고 가정하지만 동시에 데이터를 저장하는 2 개의 스레드 A와 B가 있다고 가정하면 모두 수면에 들어갑니다. 좋아, 이제 다른 스레드가 하나를 제거한 다음 스레드 A 중 하나를 깨우면 A는 저장할 수 있습니다. 저장 후 다른 스레드를 깨우십시오. B를 깨우면 현재 대기열이 가득 차 있고 B가 저장할 수 없기 때문에 문제가 발생합니다. B가 저장하면 검색되지 않은 값을 덮어 씁니다. 상태가 사용되기 때문에 저장 및 철수는이 상태를 사용하여 잠을 자고 깨어나면 엉망이됩니다. 이 시점 에서이 조건의 사용을 이해할 수 있습니다. 이제 위의 차단 대기열의 효과를 테스트하겠습니다.
public class boundedBuffer {public static void main (string [] args) {buffer buffer = new buffer (); for (int i = 0; i <5; i ++) {// 버퍼에 데이터를 저장하여 새 스레드 (new Runnable () {@override public void run () {nextint ()); (InterpruptedException e) {e.printstacktrace ();}}). start ();} for (int i = 0; i <10; i ++) {// 버퍼 새 스레드에서 데이터를 얻기 위해 10 스레드를 열고 (새 runnable () {@override public void run () {buffer.take (buffer) (// buffer retecpecture) (// buffer} e). {e.printstacktrace ();}}}). start ();}}}}데이터를 가져 오기 위해 데이터를 저장하기 위해 5 개의 스레드만이 데이터를 가져오고 데이터를 가져 오는 것을 막고 작업 결과를 보도록 의도적으로 사용했습니다.
스레드 -5가 차단되고 당분간 데이터를 검색 할 수 없습니다!
스레드 -10이 차단되고 당분간 데이터를 검색 할 수 없습니다!
스레드 -1 저장된 값 : 755
스레드 -0 저장된 값 : 206
스레드 -2 저장된 값 : 741
스레드 -3 저장된 값 : 381
스레드 -14 제거 값 : 755
스레드 -4 저장된 값 : 783
스레드 -6 값을 꺼내십시오 : 206
스레드 -7 제거 값 : 741
스레드 -8 제거 값 : 381
스레드 -9 값을 꺼내십시오 : 783
스레드 -5가 차단되고 당분간 데이터를 검색 할 수 없습니다!
스레드 11이 차단되고 당분간 데이터를 검색 할 수 없습니다!
스레드 -12가 차단되고 당분간 데이터를 검색 할 수 없습니다!
스레드 -10이 차단되고 당분간 데이터를 검색 할 수 없습니다!
스레드 -13이 차단되고 당분간 데이터를 검색 할 수 없습니다!
결과에서, 우리는 스레드 5와 10이 먼저 실행된다는 것을 알 수 있으며, 대기열에는 없으므로 차단되어 잠을 자고 있습니다. 그들은 새로운 값이 줄에 저장 될 때까지만 얻을 수 있습니다. 그러나 운이 좋지 않으며 저장된 데이터는 다른 스레드에 의해 먼저 가져옵니다. 하하 ... 그들은 몇 번 더 실행할 수 있습니다. 저장된 데이터가 차단되는 것을 보려면 데이터를 조금 덜 가져 오도록 스레드를 설정할 수 있으며 여기에서 설정하지 않습니다.
여전히 이전과 같은 질문입니다. 이제 세 개의 스레드가 실행하도록하십시오. 질문을 살펴 보겠습니다.
3 개의 스레드가 있고, 자식 스레드 1은 먼저 10 번 실행되고, 자식 스레드 2가 10 번 실행 된 다음 메인 스레드가 5 번 실행 된 다음 하위 스레드 1으로 전환 한 다음 10 번 실행하고, 하위 스레드 2가 10 번 실행되고, 메인 스레드가 5 번 실행됩니다 ...이 왕복 여행은 50 회 실행됩니다.
상태를 사용하지 않으면 실제로는 어렵지만 조건으로 수행하는 것이 매우 편리합니다. 원칙은 매우 간단합니다. 세 가지 조건을 정의합니다. Child Thread 1이 실행 된 후, Child Thread 2가 메인 스레드를 깨우고 메인 스레드가 자식 스레드 1을 깨우고 있습니다. 모닝 메커니즘은 위의 버퍼와 유사합니다. 아래 코드를 살펴 보겠습니다. 이해하기 쉽습니다.
public class threeconditioncommunication {public static void main (string [] args) {비즈니스 비즈니스 = new Business (); new Thread (new runnable () {// child ride @override public void run () {for (int i = 1; i <= 50; i ++) {bussiness.sub1 (i)}); new thread (); {// 다른 어린이 스레드 시작 @override public void run () {for (int i = 1; i <= 50; i ++) {bussiness.sub2 (i);}}}). start (); int i = 1; i <= 50; i ++) {bussiness.main (i); 조건 1 = lock.newcondition (); 조건은 조건입니다. {// (int j = 1; j <= 10; j ++) {system.out.println ( " + j +"의 " + J +", " + i);} bshouldsub = 1; 조건 2); {lock.unlock ();}} public void sub2 (int i) {lock.lock (); try {while (bshouldSub! = 1) {while {chonder2.await (); // 조건을 사용하여 Await 메소드를 호출} catch (예외 e) {// to auto-gentated catch.printstacktrace. j ++) {System.out.println ( " + j +"의 " + J +", " + i);} bshouldSub = 2; 컨디셔닝 메인 .signal (); // 메인 스레드가 실행하자 {lock.unlock ();}} public void main (int i) {try! {컨디션 메인 .await (); // 조건을 사용하여 조건을 사용하여 Await 메소드를 호출} catch (Exception e) {// todo auto-auto-auto-auto-recke.printstacktrace ();}} for (int j = 1; j <= 5; 0; 조건 1.signal (); // 스레드 1을 실행하자} 마침내 {lock.unlock ();}}}}코드는 약간 길어 보이지만 환상이며 논리는 매우 간단합니다. 그것은 스레드의 조건 기술을 요약하는 것입니다.
위는 Java 동시성 조건 차단 조건의 응용 프로그램 코드 예제에 대한이 기사의 전체 내용입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!