단일 패턴을 이용하여 전역 접근 문제를 해결하다

6819 단어 단일 모드
대상 프로그래밍에서 우리는 언제나 대상을 만들 수 있다. 왜냐하면 우리의 코드는 대상을 필요로 하기 때문이다. 그러나 주의해야 할 것은 우리가 때때로 무의미하게 대상을 만들 수도 있다는 것이다. 더욱 무서운 것은 이런 군더더기 대상들이 검색하기 어려운 BUG를 만들 수 있다는 것이다. 특히 다중 루틴 프로그래밍에서.
그래서 합리적인 생성 대상도 하나의 학문이다.
일부 대상은 우리가 하나만 필요로 하는데, 예를 들면, 스레드 탱크, 버퍼 등이다. 이런 대상은 단지 하나의 실례만 있을 뿐, 일단 여러 실례가 발생하면 문제가 발생할 수 있다.그래서 우리는 코드에 실례가 하나밖에 없다는 것을 확보하기 위해 방법을 찾아야 한다.
먼저 우리가 생각한 첫 번째 해결 방법은 전역 변수를 성명한 다음에 대상을 전역 변수에 값을 부여하는 것이다. 그러나 이것은 우리가 프로그램이 시작할 때 이 대상을 잘 만들어야 한다는 것을 의미한다. 그러나 우리는 필요할 때 대상을 만들어야 한다. 그리고 이 대상 자체가 자원을 매우 소모한다면 이것은 일종의 낭비이다.
객체 작성에 대해 언급해야 할 사항은 다음과 같습니다.
static BluetoothSocket socket = null;

자바는 사람들이 대상을 성명할 때 대상에게 초기 값을 부여하여 문제가 발생하지 않도록 격려하지만 대상은 이때 만들어지지 않습니다!진정한 창설 대상은 new와 반사 메커니즘을 통해 만들어져야 한다.전역 변수를 사용할 때 우리는 전체 프로그램에 하나밖에 없다는 것을 확보해야 한다. 전역 변수를 사용하는 목적은 자원을 공유하기 위해서이고 공유 자원은 변하지 않는 것과 공유하는 두 가지 조건에 도달해야 하기 때문이다.변하지 않는다는 것은 이 자원이 전체 프로그램에서 반드시 한 부만 있어야 한다는 것을 가리킨다. 공유란 그 변화가 공유된 모든 대상에게 보여야 한다는 것을 말한다. 그렇지 않으면 모든 대상은 자신의 한 부를 가지고 있는데 어떻게 공유할 수 있겠는가?
따라서 우리는 하나의 클래스는 하나의 실례만 있고 다른 클래스는 스스로 그 실례를 만들 수 없다는 것을 확보해야 한다.
단일 모드를 사용하면 이 점을 확보할 수 있다.
단일 모드의 의도는 하나의 클래스가 하나의 실례만 있는 것을 확보하고 전역 접근점을 제공하는 것이다.얘는 도대체 어떻게 이 정도까지 했지?
우리는 일반적인 클래스는 구조기를 통해 만들어지고 구조기는 일반적으로public, 즉 접근할 수 있다는 것을 알고 있다. 그러나 우리가 구조기를private로 설정하면 다른 클래스가 이 대상을 만드는 실례를 막을 수 있다. 그러나 문제는 다음과 같다. 개인적인 구조기는 이 클래스만 접근할 수 있지만 우리는 이런 종류의 실례를 만들 수 없다. 어떻게 이런 종류의 실례를 얻을 수 있겠는가?
이때 우리는 이 분류에서 자신의 정적 실례를 성명한 다음에 정적 방법을 통해 돌아와야 한다.우리는 정적 실례가 프로그램에 하나밖에 없다는 것을 알고 있기 때문에 이 실례가 프로그램에 하나밖에 없다는 것을 확보할 수 있다. 또한 구조기는 개인적인 것이기 때문에 다른 종류도 실례를 만들 수 없다.
다음은 단일 예제 모드를 사용하는 일반적인 방법입니다.
private static BluetoothSocket bluetoothSocket;

private BluetoothSocket(){}

public static BluetoothSicket getBluetoothSocket(){
     if(blueSocket == null){
           bluetoothSocket = new BluetoothSokcet();
     }
     return bluetoothSocket;
}

getBluetoothSocket () 는 정적 방법이기 때문에, 우리는 실례를 만들어서 이 방법을 호출할 필요가 없고, 대상을 만들 때 자주 사용하는 방법도 사용합니다. 예를 들어 실례화를 지연시키고, 정지 초기화라고도 합니다. 이 점을 이용하여 프로그램에 실례가 만들어졌는지 판단할 수 있습니다. 실례가 없으면 프로그램에 실례가 영원히 하나밖에 없다는 것을 확보할 수 있습니다.지연 실례화를 사용하는 가장 큰 장점은 우리가 필요할 때 대상을 만들 수 있다는 것이다.
단일 모드는 프로그래머가 무의미하게 전역 변수를 만드는 것을 없애기 위해서이다. 특히 초보자는 내가 프로그래밍을 시작할 때부터 전역 변수를 만드는 것을 좋아했다. 명명 공간을 고려하지 않아도 이런 것들이 정말 편하기 때문이다. 왜냐하면 그때 나는 C와 C++를 배웠기 때문이다. 자바 표면에 명명 공간이 없다고 해도 내부 메커니즘은 명명 공간을 바탕으로 한다.단지 가방 도입 메커니즘으로 우리가 이 문제에 대해 고민할 필요가 없다는 것을 확보할 뿐이다.
어떤 프로그램 언어든지 전역 변수를 사용하는 것을 장려하지 않는다는 것은 프로그래밍 구조가 좋지 않다는 것을 의미한다.
일반적인 인코딩이라면 단일 모드가 좀 쓸모가 있는 것 같지만 다중 루틴 프로그래밍과 같은 고민거리라면 단일 모드는 어느 정도에 루틴 안전을 준다.
동기화 이 화제는 우리가 자바를 배울 수 없는 것이고 매우 중요한 난점이기도 하다. 안전한 코드를 쓰려면 우리가 끊임없이 노력해야 한다.
단일 모드라도 우리는 두 개의 라인이 동시에 실례를 만들지 않을 것을 확보할 수 없다. 최악의 경우 여러 개의 라인이 동시에 정적 방법을 사용해서 동시에 실례를 만드는 것이다. 이것은 다중 라인에서 매우 흔히 볼 수 있는 현상이다.따라서, 우리는 정적 방법 전에synchronized 키워드를 추가하여 모든 라인이 이 방법에 들어가기 전에, 여러 라인이 동시에 이 방법을 사용하지 않도록 다른 라인이 이 방법을 떠나기를 기다려야 한다.
문제는 역시 왔다. 이 방법을 처음 실행할 때만 우리는 진정으로 동기화를 필요로 한다. 왜냐하면 정적 방법은 처음 호출된 후에 다시는 실례가 발생하지 않도록 확보할 수 있기 때문이다.synchronized 키워드는 이때 군더더기입니다. 첫 번째 경우에만 유용합니다. 앞으로 이 방법을 사용할 때마다 쓸데없는 라인 소모를 해야 합니다.
따라서 동기화하는 방법은 좋은 방법이 아니다. 이것은 우리의 프로그램에 무한한 대기 백엔드가 존재하게 하고 우리의 프로그램 효율을 매우 떨어뜨린다.
우리는 코드를 조금만 바꾸면 된다.
private static BluetoothSocket bluetoothSocket = new BluetoothSocket();

private BluetoothSocket(){}

public static BluetoothSocket getBluetooth(){
    return bluetoothSocket;
}

왜 이 코드는 라인의 안전을 보장할 수 있습니까?분명히 그것은 단지 지연 실례화를 폐기했을 뿐이다.JVM은 모든 스레드에서 정적 메소드를 호출하기 전에 이 인스턴스가 작성되었는지 확인할 수 있기 때문입니다.
또한 스레드의 다른 지식을 활용하여 이 작업을 수행할 수도 있습니다.
private volatile static BluetoothSocket bluetoothSocket;

private BluetoothSocket(){}

public static BluetoothSicket getBluetoothSocket(){
     if(blueSocket == null){
           synchronized(BluetoothSocket.class){
               if(blueSocket == null){
                  bluetoothSocket = new BluetoothSokcet();
               }
           }
     }
     return bluetoothSocket;
}

이것이 바로 다중 검사에 자물쇠를 채우는 방법이다.우리는 먼저 실례가 이미 만들어졌는지 확인하고, 만약 아직 만들어지지 않았다면 동기화할 수 없습니다.volatile 키워드는 실례가 만들어졌을 때 모든 라인이 이 변수를 정확하게 처리할 수 있도록 합니다.정확한 처리가 무엇인지는 바로volatile을 이용하여 이 실례를 동기화한 것이다. 이 실례가 변화할 때 다른 공유 라인도 알고 해당하는 처리를 할 수 있다.다중 검사 잠금은 대상 잠금을 이용해야 합니다. 모든 자바 대상에 잠금이 있습니다. 한 라인이 이 잠금을 가져오면 다른 라인이 이 대상에 접근하려고 시도하는 것을 방지합니다. 이 라인이 이 대상의 잠금을 풀지 않으면.volatile는 일반적으로 대상 자물쇠와 함께 조합해야만 진정한 역할을 발휘할 수 있다. 하나는 변화를 통제하고, 다른 하나는 방문을 통제한다.
단일 모드가 하나의 실례를 확보할 수 있는 것도 하나의 클래스 캐리어만 있는 전제에서 두 개 이상의 클래스 캐리어가 있으면 여러 개의 단일 캐리어가 병존하는 이상한 현상이 발생할 수 있다.그래서, 이때 우리는 클래스 마운트를 지정해야 한다.그러나 일반적인 프로그램은 모두 하나의 클래스 마운트기만 있지만, 다중 라인과 관련이 있다면 이것은 정말 모른다.
총괄적으로 말하면 단례 모델의 가장 큰 역할은 한 대상의 직책을 모두 하나의 실례에 집중시키는 것이다. 이렇게 하면 무의미한 낭비를 피할 수 있다. 그러나 단례 모델도 함부로 사용할 수 있는 것이 아니라 전체 변수의 사용과 같다. 모든 직책을 하나의 실례에 맡긴다. 이것은 실례 자체가 불공평하고 특히 직책이 매우 중대한 때이다.
      

좋은 웹페이지 즐겨찾기