Java 병렬 새 위젯의 Exchanger

4341 단어 병발교환
Exchanger는 두 작업 사이에서 객체를 교환하는 울타리입니다.두 임무가 울타리에 들어갈 때, 그들은 각자 하나의 대상을 가지고 있으며, 그들이 떠날 때, 그들은 모두 상대방의 대상을 가지고 있다.Exchanger의 전형적인 응용 장면은 하나의 임무가 대상을 만들고 이 대상의 생산 대가가 높으며 다른 임무가 이 대상을 소비하는 것이다.이런 방식을 통해 더 많은 대상이 창설되는 동시에 소비될 수 있다.
Exchanger 클래스를 보여주기 위해 생산자와 소비자 임무를 만들 것입니다.Exchanger Producer와 Exchanger Consumer는 교환을 요구하는 대상으로 List을 사용합니다. 이 List에 사용되는 Exchanger를 포함합니다.Exchanger를 호출하면exchange () 방법은 상대방 작업이 자신의 exchange () 방법을 호출할 때까지 막습니다. 이 두 exchange () 방법은 동시에 완성되고 List는 교환됩니다.
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class ExchangerProducer implements Runnable {
    private List<Fat> holder;
    private Exchanger<List<Fat>> exchanger;
    public ExchangerProducer(Exchanger<List<Fat>> exchanger, List<Fat> holder) {
        this.exchanger = exchanger;
        this.holder = holder;
    }
    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                //    
                for (int i = 0;i < ExchangerDemo.size; i++) {
                    holder.add(new Fat());
                }
                //    
                holder = exchanger.exchange(holder);
            }
        } catch (InterruptedException e) {
        }
        System.out.println("Producer stopped.");
    }
}

class ExchangerConsumer implements Runnable {
    private List<Fat> holder;
    private Exchanger<List<Fat>> exchanger;
    private volatile Fat value;
    private static int num = 0;
    public ExchangerConsumer(Exchanger<List<Fat>> exchanger, List<Fat> holder) {
        this.exchanger = exchanger;
        this.holder = holder;
    }
    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                //    
                holder = exchanger.exchange(holder);
                //         
                for (Fat x : holder) {
                    num++;
                    value = x;
                    //        ,   CopyOnWriteArrayList      
                    holder.remove(x);
                }
                if (num % 10000 == 0) {
                    System.out.println("Exchanged count=" + num);
                }
            }
        } catch (InterruptedException e) {
            
        }
        System.out.println("Consumer stopped. Final value: " + value);
    }
}

public class ExchangerDemo {
    static int size = 10;
    static int delay = 5; // 
    public static void main(String[] args) throws Exception {
        ExecutorService exec = Executors.newCachedThreadPool();
        List<Fat> producerList = new CopyOnWriteArrayList<>();
        List<Fat> consumerList = new CopyOnWriteArrayList<>();
        Exchanger<List<Fat>> exchanger = new Exchanger<>();
        exec.execute(new ExchangerProducer(exchanger, producerList));
        exec.execute(new ExchangerConsumer(exchanger, consumerList));
        TimeUnit.SECONDS.sleep(delay);
        exec.shutdownNow();
    }
}

class Fat {
    private volatile double d;
    private static int counter = 1;
    private final int id = counter++;
    public Fat() {
        //         
        for (int i = 1; i<10000; i++) {
            d += (Math.PI + Math.E) / (double)i;
        }
    }
    public void print() {System.out.println(this);}
    public String toString() {return "Fat id=" + id;}
}

실행 결과(가능한 결과):
Exchanged count=10000
Exchanged count=20000
Exchanged count=30000
Exchanged count=40000
Exchanged count=50000
Exchanged count=60000
Exchanged count=70000
Exchanged count=80000
Consumer stopped. Final value: Fat id=88300
Producer stopped.

main () 에서 두 작업에 사용할 단일한 Exchanger, 교환에 사용할 CopyOnWrite Array List 두 개를 만들었습니다.이 특정한List 변체는 목록이 옮겨다닐 때remove () 방법을 호출할 수 있으며, Concurrent Modified Exception 이상을 던지지 않습니다.Exchanger Producer는 이 리스트를 채운 다음, 이 가득 찬 목록을 Exchanger Consumer의 빈 목록과 교환합니다.교환 후 Exchanger Producer는 계속 Fat 대상을 생산할 수 있고 Exchanger Consumer는 목록에 가득한 대상을 사용하기 시작합니다.Exchanger가 있기 때문에, 하나의 목록을 채우고 다른 목록을 소비하는 것이 동시에 발생한다.

좋은 웹페이지 즐겨찾기