cool hit counter Principle analysis of the concurrency toolkit concurrent package and its use_Intefrankly

Principle analysis of the concurrency toolkit concurrent package and its use


1. Class classification diagram under java.util.concurrent package

  • locks section: explicit locks (mutually exclusive and tachyon locks) are relevant.
  • atomicpart: Atomic variables class related, is the construction of a non- blockage Foundations of the algorithm;
  • executor section: thread pool related.
  • Collections section: concurrent container-related.
  • tools section: synchronization tools related to functions such as semaphores, closures, fences, etc..

1、1collectionspart:

1、1、1 BlockingQueue

   BlockingQueue is an interface, and if it were him, it would need to use a subclass that implements him.

  BlockingQueue The subclasses of'

    ArrayBlockingQueue;

    DelayQueue;

    LinkedBlockingQueue;

    SynchronousQueue;

    PriorirtyBlockingQueue;

    TransferQueue;

BlockingQueue Usage

BlockingQueue is typically used in scenarios where one thread produces objects and another thread consumes them. The following diagram illustrates this principle.

A BlockingQueue that one thread puts inside and another thread takes from inside.

A thread will continuously produce new objects and insert them into the up to in the queue, straightforward up to queue up to up to The critical mass it can accommodate。 that is say, It is limited。 If that blockage formation up to reached its tipping point, The thread responsible for production will occur when inserting a new object into the blockage。 It will always be in blockage inside, straightforward up to The thread responsible for consumption takes an object from the queue。 The thread in charge of consumption will always be removed from that blockage Taking out objects from the queue。 If the consuming thread tries to fetch an object from an empty queue, This consumer thread will be in the blockage inside, straightforward up to A production line thread drops an object into a queue。

Methods of BlockingQueue

BlockingQueue has 4 different sets of methods for inserting, removing, and inspecting elements in the queue. Each method behaves differently if the requested operation cannot be executed immediately. These methods are as follows.

Four different sets of behavioural patterns are explained.

throw an exception : Throws an exception if the attempted operation cannot be executed immediately. particular value : Returns a specific value (often true / false) if the attempted operation cannot be executed immediately. blockage : If the attempted operation cannot be executed immediately, the method call will block until it can be executed. timeout: If the attempted operation cannot be executed immediately, This method call will occur blockage, straightforward up to Able to implement, But the waiting time will not exceed the given value。 Return a particular value to tell if the operation was successful( Typical are true / false)。

Cannot insert a null into a BlockingQueue. If you try to insert a null, the BlockingQueue will throw a NullPointerException.

Accessible up to BlockingQueue All elements in the, And not just the beginning and end elements。 for example, You put an object into a queue to wait for processing, But your app wants to cancel it out。 Then you can call something like remove(o) method to remove a specific object from the queue。 But it's not very efficient.( translator's note: Queue-based data structures, Getting objects other than the start or end position is not too efficient), So you try not to use this type of method, Unless you really have to.。

Example of using BlockingQueue in Java

Here is an example of using BlockingQueue in Java. This example uses the ArrayBlockingQueue implementation of the BlockingQueue interface.

First, the BlockingQueueExample class starts a Producer and a Consumer in two separate threads.

The Producer injects strings into a shared BlockingQueue, and the Consumer takes them out of it.

public class BlockingQueueExample { 
 
    public static void main(String[] args) throws Exception { 
 
        BlockingQueue queue = new ArrayBlockingQueue(1024); 
 
        Producer producer = new Producer(queue); 
        Consumer consumer = new Consumer(queue); 
 
        new Thread(producer).start(); 
        new Thread(consumer).start(); 
 
        Thread.sleep(4000); 
    } 
}

Here are Producer kind。 Note that it is not available in every put() How it sleeps for a second when called。 This will result in Consumer Occurs while waiting for an object in the queue blockage。

public class Producer implements Runnable{ 
 
    protected BlockingQueue queue = null; 
 
    public Producer(BlockingQueue queue) { 
        this.queue = queue; 
    } 
 
    public void run() { 
        try { 
            queue.put("1"); // No need to consider security issues  Direct use
            Thread.sleep(1000); 
            queue.put("2"); 
            Thread.sleep(1000); 
            queue.put("3"); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
    } 
}

The following is the Consumer class. It just takes objects out of the queue and prints them to System.out.

public class Consumer implements Runnable{ 
 
    protected BlockingQueue queue = null; 
 
    public Consumer(BlockingQueue queue) { 
        this.queue = queue; 
    } 
 
    public void run() { 
        try { 
            System.out.println(queue.take()); 
            System.out.println(queue.take()); 
            System.out.println(queue.take()); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
    } 
}

ArrayBlockingQueue

   The ArrayBlockingQueue class implements the BlockingQueue interface.

  ArrayBlockingQueue It's a bounded blockage formation, Its internal implementation is to put the object up to In an array。 Being bounded also means, It is not capable of storing an infinite number of elements。 It has an upper limit on the number of elements that can be stored at the same time。

   You can set this limit when you initialize it, but you can't modify it afterwards (translation: because it is based on an array implementation, it also has the characteristics of an array: once initialized, the size can't be modified).

   'ArrayBlockingQueue stores elements internally in FIFO (first-in-first-out) order. The head element in the queue is the one that takes the longest to put in among all the elements, while the tail element is the shortest.

   See the code example above for an example of using ArrayBlockingQueue.

4. Delay Queue DelayQueue

DelayQueue Achieved BlockingQueue interface。DelayQueue Hold straight for elements up to A specific delay up to period。 The elements injected into it must implement the java.util.concurrent.Delayed interface, The interface defines:

public interface Delayed extends Comparable<Delayed< { 
 
  public long getDelay(TimeUnit timeUnit);   // Note the use of TimeUnit here
 
}

The DelayQueue will not release each element until after the time period of the value returned by the getDelay() method of that element. If 0 or a negative value is returned, the delay will be considered expired and the element will be released when the next take of the DelayQueue is called.

That is, the element expiration time is returned via getDelay and the object can be removed in the delay queue only after the element has existed in the queue for longer than that time.

The getDelay instance passed to the getDelay method is an enumerated type that indicates the time period that will be delayed.

The TimeUnit enumeration will take the following values.

DAYS 
HOURS 
MINUTES 
SECONDS 
MILLISECONDS 
MICROSECONDS 
NANOSECONDS

As you can see. up to of,Delayed interface also inherits from the java.lang.Comparable interface, This also means that Delayed Comparisons can be made between objects。 This one is in the case of the DelayQueue Sorting the elements in the queue on add, So they can be released in an orderly manner based on the expiration time。 The following is a list of the uses of DelayQueue examples of:

DelayQueue Two use cases of the:【 Note that the case is illustrated with up to finish concrrent chartered tools undercountDownLatch If that part is not understood see first 1.2 sectoral Tools】

1、2 Toolspart:

   CountDownLatch Usage

   The CountDownLatch class is located under the java.util.concurrent package and can be used to implement counter-like functionality. For example, if there is a task A, which has to wait for the other 4 tasks to finish executing before it can be executed, it is possible to use CountDownLatch to achieve this function.

   In layman's terms. even useCountDownLatch time Several threads use the sameCountDownLatch targets There is a thread that callswait approach Other threads usecountDown() approach, When the final counter is minus up to0 at the time of,wait call center Continue down the line.;

   The CountDownLatch class provides only one constructor: the

 public CountDownLatch(int count) { }   //The parameter count is the count value

Then the following 3 methods are the most important methods in the CountDownLatch class.

 public void await() throws InterruptedException { }    // The thread that calls the await() method will be hung, it will wait until the count value is 0 before continuing execution
 public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }   // Similar to await(), except that if the count value does not change to 0 after a certain amount of time, execution will continue
 public void countDown() { };   //Subtract count value by 1

See examples of use below.

public class Test {
     public static void main(String[] args) {   
         final CountDownLatch latch = new CountDownLatch(2);
 
         new Thread(){
             public void run() {
                 try {
                     System.out.println(" subthread"+Thread.currentThread().getName()+" Under implementation");
                    Thread.sleep(3000);
                    System.out.println(" subthread"+Thread.currentThread().getName()+" Implementation completed");
                    latch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             };
         }.start();
 
         new Thread(){
             public void run() {
                 try {
                     System.out.println(" subthread"+Thread.currentThread().getName()+" Under implementation");
                     Thread.sleep(3000);
                     System.out.println(" subthread"+Thread.currentThread().getName()+" Implementation completed");
                     latch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             };
         }.start();
 
         try {
             System.out.println(" Waiting for the 2 sub threads to finish executing...");
            latch.await();
            System.out.println(" 2 sub-threads have been executed");
            System.out.println(" Continue with the main thread");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
     }
}

Implementation results.

 Thread Thread-0 is executing
 Thread Thread-1 is executing
 Waiting for the 2 sub threads to finish executing...
 Thread Thread-0 is executed
 Thread Thread-1 is executed
 2 sub-threads have been executed
 Continue with the main thread

CyclicBarrier Usage

A literal loopback fence, by which a group of threads can be made to wait until a certain state before they all execute at the same time. It's called a loopback because the CyclicBarrier can be reused after all waiting threads have been released. Let's call this state a barrier for now, after calling the await() method, the thread is in a barrier.

In layman's terms, you use the CyclicBrarrier to call the wait method of the CyclicBrarrier object when several threads reach the fence, and then unify the execution when all the objects have reached the fence.

CyclicBarrier class is located under the java.util.concurrent package, CyclicBarrier provides 2 constructors.

public CyclicBarrier(int parties, Runnable barrierAction) {
}
 
public CyclicBarrier(int parties) {
}

The parameter parties means how many threads or tasks are allowed to wait until the barrier state.

parametersbarrierAction for when all these threads reach up tobarrier What will be executed when the status; in fact, it is When all threads up to Behind the fence., If you need to perform an additional action before releasing, It is possible to achieverunnable ofrun approach, At this point a thread will be called to executerun approach;

Then the most important method in CyclicBarrier is the await method, which has 2 overloaded versions.

public int await() throws InterruptedException, BrokenBarrierException { };
public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { };

The first version is more commonly used to hang the current thread until all threads have reached the barrier state before executing subsequent tasks simultaneously.

The second version is to let these threads wait until a certain time, and if there are still threads that haven't reached the barrier state then directly let the threads that have reached the barrier perform subsequent tasks.

Here are a few examples to make it clear.

Assuming that several threads have to perform write data operations and that these threads can only continue to do later things once all threads have completed their write data operations, the CyclicBarrier can be utilized.

public class Test {
    public static void main(String[] args) {
        int N = 4;
        CyclicBarrier barrier  = new CyclicBarrier(N);
        for(int i=0;i<N;i++)
            new Writer(barrier).start();
    }
    static class Writer extends Thread{
        private CyclicBarrier cyclicBarrier;
        public Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }
 
        @Override
        public void run() {
            System.out.println(" threads"+Thread.currentThread().getName()+" Data being written...");
            try {
                 Thread.sleep(5000);       // Simulate write data operations with sleep
                System.out.println(" threads"+Thread.currentThread().getName()+" Write data complete, Wait for other threads to finish writing");
                cyclicBarrier.await(); // Where the fence is  All threads stay here and wait for other threads to execute up to this
            } catch (InterruptedException e) {
                e.printStackTrace();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
            System.out.println(" All threads are written and continue to process other tasks...");
        }
    }
}

Test results.

 Thread Thread-0 is writing data...
 Thread-3 is writing data...
 Thread-2 is writing data...
 Thread Thread-1 is writing data...
 Thread Thread-2 finishes writing data and waits for other threads to finish writing
 Thread Thread-0 finishes writing data and waits for other threads to finish writing
 Thread-3 finishes writing data and waits for other threads to finish writing
 Thread Thread-1 finishes writing data and waits for other threads to finish writing
 All threads are written and continue to process other tasks...
 All threads are written and continue to process other tasks...
 All threads are written and continue to process other tasks...
 All threads are written and continue to process other tasks...

   As you can see from the output above, each write thread is waiting for the other threads to finish their write operations after they have performed their write data operations.

   Once all threads thread write operations are complete, all threads move on to subsequent operations.

   If it is said that you want to perform additional other operations after all threads have finished writing operations you can provide the CyclicBarrier with the Runnable parameter.

public class Test {
    public static void main(String[] args) {
        int N = 4;
        CyclicBarrier barrier  = new CyclicBarrier(N,new Runnable() {
            @Override
            public void run() {
                System.out.println(" current thread"+Thread.currentThread().getName());   
            }
        });
 
        for(int i=0;i<N;i++)
            new Writer(barrier).start();
    }
    static class Writer extends Thread{
        private CyclicBarrier cyclicBarrier;
        public Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }
 
        @Override
        public void run() {
            System.out.println(" threads"+Thread.currentThread().getName()+" Data being written...");
            try {
                 Thread.sleep(5000);       // Simulate write data operations with sleep
                System.out.println(" threads"+Thread.currentThread().getName()+" Write data complete, Wait for other threads to finish writing");
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
            System.out.println(" All threads are written and continue to process other tasks...");
        }
    }
}

Test results.

 Thread Thread-0 is writing data...
 Thread Thread-1 is writing data...
 Thread-2 is writing data...
 Thread-3 is writing data...
 Thread Thread-0 finishes writing data and waits for other threads to finish writing
 Thread Thread-1 finishes writing data and waits for other threads to finish writing
 Thread Thread-2 finishes writing data and waits for other threads to finish writing
 Thread-3 finishes writing data and waits for other threads to finish writing
 Current thread Thread-3
 All threads are written and continue to process other tasks...
 All threads are written and continue to process other tasks...
 All threads are written and continue to process other tasks...
 All threads are written and continue to process other tasks...

When the fence at thewait When the method is used with a set time parameter, While waitingBarrier in the course of After the time limit Just throw an exception and continue with the next task。

Case code.

public class Test {
    public static void main(String[] args) {
        int N = 4;
        CyclicBarrier barrier  = new CyclicBarrier(N);
 
        for(int i=0;i<N;i++) {
            if(i<N-1)
                new Writer(barrier).start();
            else {                                // Last thread waiting5000 Execute after milliseconds, So that other threads will occur timeout  throw an exception
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                new Writer(barrier).start();
            }
        }
    }
    static class Writer extends Thread{
        private CyclicBarrier cyclicBarrier;
        public Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }
 
        @Override
        public void run() {
            System.out.println(" threads"+Thread.currentThread().getName()+" Data being written...");
            try {
                 Thread.sleep(5000);       // Simulate write data operations with sleep
                System.out.println(" threads"+Thread.currentThread().getName()+" Write data complete, Wait for other threads to finish writing");
                try {
                    cyclicBarrier.await(2000, TimeUnit.MILLISECONDS);
                } catch (TimeoutException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" All threads are written and continue to process other tasks...");
        }
    }
}
 Thread Thread-0 is writing data...
 Thread-2 is writing data...
 Thread Thread-1 is writing data...
 Thread Thread-2 finishes writing data and waits for other threads to finish writing
 Thread Thread-0 finishes writing data and waits for other threads to finish writing
 Thread Thread-1 finishes writing data and waits for other threads to finish writing
 Thread-3 is writing data...
java.util.concurrent.TimeoutException
Thread-1 All threads are written and continue to process other tasks...
Thread-0 All threads are written and continue to process other tasks...
    at java.util.concurrent.CyclicBarrier.dowait(Unknown Source)
    at java.util.concurrent.CyclicBarrier.await(Unknown Source)
    at com.cxh.test1.Test$Writer.run(Test.java:58)
java.util.concurrent.BrokenBarrierException
    at java.util.concurrent.CyclicBarrier.dowait(Unknown Source)
    at java.util.concurrent.CyclicBarrier.await(Unknown Source)
    at com.cxh.test1.Test$Writer.run(Test.java:58)
java.util.concurrent.BrokenBarrierException
    at java.util.concurrent.CyclicBarrier.dowait(Unknown Source)
    at java.util.concurrent.CyclicBarrier.await(Unknown Source)
    at com.cxh.test1.Test$Writer.run(Test.java:58)
Thread-2 All threads are written and continue to process other tasks...
java.util.concurrent.BrokenBarrierException
 Thread-3 finishes writing data and waits for other threads to finish writing
    at java.util.concurrent.CyclicBarrier.dowait(Unknown Source)
    at java.util.concurrent.CyclicBarrier.await(Unknown Source)
    at com.cxh.test1.Test$Writer.run(Test.java:58)
Thread-3 All threads are written and continue to process other tasks...

Also CyclicBarrier is reusable, see the following example.

public class Test {
    public static void main(String[] args) {
        int N = 4;
        CyclicBarrier barrier  = new CyclicBarrier(N);
 
        for(int i=0;i<N;i++) {
            new Writer(barrier).start();
        }
 
        try {
            Thread.sleep(25000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        System.out.println(" CyclicBarrier Reuse");
 
        for(int i=0;i<N;i++) {
            new Writer(barrier).start();
        }
    }
    static class Writer extends Thread{
        private CyclicBarrier cyclicBarrier;
        public Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }
 
        @Override
        public void run() {
            System.out.println(" threads"+Thread.currentThread().getName()+" Data being written...");
            try {
                 Thread.sleep(5000);       // Simulate write data operations with sleep
                System.out.println(" threads"+Thread.currentThread().getName()+" Write data complete, Wait for other threads to finish writing");
 
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" All threads are written and continue to process other tasks...");
        }
    }
}

Test results.

 Thread Thread-0 is writing data...
 Thread Thread-1 is writing data...
 Thread-3 is writing data...
 Thread-2 is writing data...
 Thread Thread-1 finishes writing data and waits for other threads to finish writing
 Thread-3 finishes writing data and waits for other threads to finish writing
 Thread Thread-2 finishes writing data and waits for other threads to finish writing
 Thread Thread-0 finishes writing data and waits for other threads to finish writing
Thread-0 All threads are written and continue to process other tasks...
Thread-3 All threads are written and continue to process other tasks...
Thread-1 All threads are written and continue to process other tasks...
Thread-2 All threads are written and continue to process other tasks...
 CyclicBarrier Reuse
 Thread-4 is writing data...
 Thread-5 is writing data...
 Thread-6 is writing data...
 Thread-7 is writing data...
 Thread Thread-7 finishes writing data and waits for other threads to finish writing
 Thread Thread-5 finishes writing data and waits for other threads to finish writing
Thread Thread-6 finishes writing data and waits for other threads to finish writing
 Thread Thread-4 finishes writing data and waits for other threads to finish writing
Thread-4 All threads are written and continue to process other tasks...
Thread-5 All threads are written and continue to process other tasks...
Thread-6 All threads are written and continue to process other tasks...
Thread-7 All threads are written and continue to process other tasks...

Semaphore Usage

   Semaphore translates literally as a semaphore. Semaphore can control the number of threads that can be accessed at the same time by acquiring a permission, waiting if there is none, and releasing a permission by releasing().

   The Semaphore class is located under the java.util.concurrent package and it provides 2 constructors.

 public Semaphore(int permits) { // the parameter permits indicates the number of permits, i.e. how many threads can be allowed to access at the same time
    sync = new NonfairSync(permits);
}
 public Semaphore(int permits, boolean fair) { //this has an extra parameter fair to indicate whether it is fair, i.e. the longer you wait the longer you get the permit first
    sync = (fair)? new FairSync(permits) : new NonfairSync(permits);
}

Here are a few of the more important methods in the Semaphore class, starting with the acquire(), release() methods.

 public void acquire() throws InterruptedException { } //acquire a permit
 public void acquire(int permits) throws InterruptedException { } //get permissions
 public void release() { } //release a license
 public void release(int permits) { } //release permits

acquire() Used to get a permit, If no permit can be obtained, Then it will wait., straightforward up to Obtaining permission。

release() is used to release the license. Note that permission must be obtained before it can be released.

this4 methods will be blockage, If you want to get it right away up to The result of the execution, There are several ways to do this

 public boolean tryAcquire() { }     //attempt to get a permit and return true immediately if it succeeds, or false if it fails
 public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException { }   // Attempt to obtain a permit and return true immediately if it succeeds within the specified time, otherwise return false immediately
 public boolean tryAcquire(int permits) { }  //try to get permissions, return true immediately if it succeeds, return false immediately if it fails
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException { }  //try to get permissions, return true immediately if successful within the specified time, otherwise return false immediately

Here is an example to see the specific use of Semaphore.

Suppose a factory has 5 machines, but 8 workers, and a machine can only be used by one worker at a time, and only when it is used up can the other workers continue to use it. Then we can do it with Semaphore: [acquire is blocking waiting to get permission to execute]

public class Test {
    public static void main(String[] args) {
         int N = 8;             //Number of workers/workers
         Semaphore semaphore = new Semaphore(5);  //Number of machines
        for(int i=0;i<N;i++)
            new Worker(i,semaphore).start();
    }
 
    static class Worker extends Thread{
        private int num;
        private Semaphore semaphore;
        public Worker(int num,Semaphore semaphore){
            this.num = num;
            this.semaphore = semaphore;
        }
 
        @Override
        public void run() {
            try {
                semaphore.acquire(); // If a new thread enters, it cannot be licensed   will blockage  straightforward up to Get permission and then proceed
           //The number of threads of concurrent execution depends on the number of semaphores configured, which is the number of resources available.

                System.out.println(" worker"+this.num+" Occupancy of a machine in production...");
                Thread.sleep(2000);
                System.out.println(" worker"+this.num+" Release the machine");
                 semaphore.release();     //Release permission       
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Test results.

 Workers 0 occupy a machine in the production...
 Worker 1 occupies a machine in the production...
 Worker 2 occupies a machine in production...
 Worker 4 occupies a machine in production...
 Worker 5 occupies a machine in production...
 Worker 0 releases the machine
 Worker 2 releases the machine
 Worker 3 occupies a machine in production...
 Worker 7 occupies a machine in production...
 Worker 4 releases the machine
 Worker 5 releases the machine
 Worker 1 releases the machine
 Worker 6 occupies a machine in the production...
 Worker 3 releases the machine
 Worker 7 releases the machine
 Worker 6 releases the machine

exchanger Usage

   Exchanger is a fence that exchanges objects between two tasks, and when these tasks enter the fence, they each have an object. When they leave, they both have the object previously held by the object.

It is typically applied in a scenario where one task is creating objects, which are costly to produce, and another task is consuming them. By doing this, more objects can be consumed as they are created.

public class ExchangerTest {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        final Exchanger exchanger = new Exchanger();
        executor.execute(new Runnable() {
            String data1 = "Ling";

            @Override
            public void run() {
                doExchangeWork(data1, exchanger);
            }
        });

        executor.execute(new Runnable() {
            String data2 = "huhx";

            @Override
            public void run() {
                doExchangeWork(data2, exchanger);
            }
        });
        executor.shutdown(); // Disable the thread pool.  Release of resources
    }

    private static void doExchangeWork(String data1, Exchanger exchanger) {
        try {
            System.out.println(Thread.currentThread().getName() + " The data is being put " + data1 + "  Exchange out");
            Thread.sleep((long) (Math.random() * 1000));

            String data2 = (String) exchanger.exchange(data1);
            System.out.println(Thread.currentThread().getName() + " Exchange of data  up to  " + data2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Tools Summary.

The following is a summary of the three auxiliary classes mentioned above.

1) Both CountDownLatch and CyclicBarrier are capable of implementing waiting between threads, except that they have different emphases.

CountDownLatch is generally used for a thread A to wait for a number of other threads to finish executing a task before it executes.

Whereas CyclicBarrier is generally used for a group of threads waiting for each other to reach a certain state, before that group of threads executes simultaneously.

Also, CountDownLatch is not reusable, while CyclicBarrier is reusable.

2) Semaphore is actually somewhat similar to a lock in that it is generally used to control access to a certain set of resources.


Recommended>>
1、Data Science in Internet Financial Risk Control
2、WampServer Easy to build PHP development environment on Windows
3、Ive seen you Youre the one who likes Stream
4、chrony clock source configuration
5、SupportAnnotationLibrary Usage Details

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号