Eight, java multithreading foundation of knowledge and contract summary

I. Background

1. previous blog we introduced the basics of multithreading and their practical examples for us today and say java contract following knowledge, previous articles can refer to my previous blog, but if there says wrong, please correct me welcome message.

2. The purpose of writing this blog is to improve their knowledge under the network, there is the use to which the actual project, but also hope to help everyone to better understand the knowledge, usually under accumulate, subtle is formed strong knowledge network, and ado, let us work together to learn under the bar.

Second, synchronous containers (and under contract)

ArrayList and the difference 1.Vector

1.1.ArrayList List is the most common implementation class, the interior is achieved through an array of elements that allows for fast random access. The disadvantage is that the array can not have a space between each element when the array size does not satisfy the need to increase storage capacity, it is necessary to speak has been copied to the new array of data storage space. When inserting or deleting an element from the intermediate position of ArrayList, the array is required to copy, move, the cost is relatively high. Therefore, it is suitable for random search and traversal, not suitable for insertion and deletion.

1.2.Vector and ArrayList, just as through the array to achieve, except that it supports thread synchronization, that only one thread at a time can write Vector, avoid multi-threading while writing the inconsistency caused, but it requires high synchronization the cost, therefore, have access to it than slower access ArrayList

Note:  the Vector thread- safe, ArrayList thread is unsafe

Source Vector Class (the Add () method of class source code)

ArrayList source type (source Add () method)

2.HashTable与HashMap

2.1.HashMap not thread-safe, the HashMap is sub-interface is an interface map interface, the object is mapped to a key value, wherein the keys and values ​​are objects, and can not contain duplicate keys, but may contain a duplicate value. HashMap allows null key and null value, and hashtable is not allowed.

2.2.HashTable Collection is a thread-safe.

2.3.HashMap Hashtable is lightweight realization (non-thread-safe implementation), they have completed the Map interface, the main difference is that HashMap allows null (null) key (key), due to the non-thread-safe, efficiency may be higher than Hashtable.
HashMap allows null as a key entry or the value, and not allowed Hashtable.
HashMap Hashtable contains methods removed, replaced containsvalue containsKey.

Note: HashTable thread- safe, HashMap thread- unsafe .

3.ConcurrentHashMap

3.1 Because the HashTable locked safe, but can only make a thread locking operation, so the impact of efficiency, this time invented ConcurrentHashMap, the principle as shown below:

There are two interfaces at 3.2.ConcurrentMap important realization:
ConcurrentHashMap
ConcurrentSkipListMap (. Support concurrent sorting function to compensate for the p-HMA ConcurrentHas)
ConcurrentHashMap internal use segment (Segment) to represent these different sections, each section is actually a
small HashTable, they It has its own lock. As long as multiple modifications occur in different sections, and they can
send performed. The whole is divided into a 16 segment (Segment. I.e. up to 16 concurrent threads modifying operation.
This is also the scene heavy thread lock granularity is reduced thereby reducing lock contention of a solution. Most of the code and the shared variables
usage of volatile keyword to declare the purpose of obtaining the first time modify the content of the performance is very good.

4.CountDownLatch

4.1.CountDownLatch class java.util.concurrent located under the package, which may be implemented using functionally similar counter. For example, there is a task A, it waits for the other to perform after the completion of four tasks to perform, then you can use this function to achieve the CountDownLatch (similar to the join () method).

4.2. Code

public class Test002 {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("等待子线程执行完毕...");
        CountDownLatch countDownLatch = new CountDownLatch(2);
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程," + Thread.currentThread().getName() + "开始执行...");
                countDownLatch.countDown();// 每次减去1
                System.out.println("子线程," + Thread.currentThread().getName() + "结束执行...");
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程," + Thread.currentThread().getName() + "开始执行...");
                countDownLatch.countDown();
                System.out.println("子线程," + Thread.currentThread().getName() + "结束执行...");
            }
        }).start();
        countDownLatch.await();// 调用当前方法主线程阻塞  countDown结果为0, 阻塞变为运行状态
        System.out.println("两个子线程执行完毕....");
        System.out.println("继续主线程执行..");
    }
}

4.3 Results

Third, concurrent queue

1. On the JDK provides two concurrent queue implementation, is a high-performance ConcurrentLinkedQueue represented queue, a representative of the interface is BlockingQueue blocking queue, no matter what are inherited from the Queue.

2.ConcurrentLinkedQueue: is a scene suitable for a highly concurrent queue, lock-free by the way, to achieve high performance under high concurrency state, ConcurrentLinkedQueue generally good performance in BlockingQueue it is based on linked nodes. Unbounded thread-safe queue . Elements of the queue to follow the FIFO principle. The first head is joined, the end of the latest addition, the queue does not allow null elements.

2.1.ConcurrentLinkedQueue important methods: add and offer () is a method of adding elements (maybe not in ConcurrentLinkedQueue in a method of any difference)
poll () and peek () is to take the first element node, except that it removes the element, the latter will not.

2.2 Code (self facie results)

ConcurrentLinkedDeque q = new ConcurrentLinkedDeque();
	q.offer("小明");
	q.offer("小红");
	q.offer("小张");
	q.offer("小诺");
	q.offer("小华");
	//从头获取元素,删除该元素
	System.out.println(q.poll());
	//从头获取元素,不刪除该元素
	System.out.println(q.peek());
	//获取总长度
	System.out.println(q.size());

3.BlockingQueue: blocking queue (BlockingQueue) is a two queues support additional operations. These two additional operations are:

3.1. In the queue is empty when retrieving an element of thread waits for the queue to become non-empty.
When the queue is full, the thread will wait queue storage elements available. 

Blocking queue commonly used in the producers and consumers of the scene, the producer is added to the queue thread elements, the consumer is to take elements from the queue thread. Blocking queue storage container element is the producers, and consumers only take elements from the container.

3.2.BlockingQueue that is blocking queue from blocking can be seen in the word, and in some cases blocked access to the queue may cause blocking. There are cases blocked major following two:

1. When the queue is full when carried into queues

2. When the queue time for an empty queue operation

Therefore, when a thread attempts to have a full queue of queues into operation, it will be blocked, unless there is another thread to do the queue operation; Similarly, when a thread tries to empty the queue queue operation , it will be blocked, unless there is another thread into the queue operation.

3. In Java, BlockingQueue interface located in the java.util.concurrent package (available starting Java5 version), by blocking queue characteristics described above shows that blocking queue is thread-safe.

In the new Concurrent package, BlockingQueue good solution to multiple threads, how efficient and safe "transfer" of data problems. These efficient and thread-safe queue class, a great convenience for us to quickly build high-quality multi-threaded programs. This paper describes the BlockingQueue all members of the family, including their respective functions and common usage scenarios.

Understanding BlockingQueue

Blocking queue, as the name implies, it is a first queue and a queue data structure role substantially as shown below:

From the figure we can see clearly through a shared queue, so that the data can be input from one end of the queue is output from the other end;

Queuing, there are two main :( different implementations of course, also may extend many different types of queues, a DelayQueue is one of them)

  First In First Out (FIFO): the first elements are also inserted into the first queue of the queue, the queue functions like. To some extent, this also reflects a queue fairness.

  Last in, first out (LIFO): After you insert the first element of the queue queue, the queue priority of recent events.

      Multi-threaded environment, data sharing can be easily achieved through the queue, such as the classic "producer" and "consumer" model, it can facilitate data sharing between the two through the queue. Suppose we have a number of producer thread, there are a number of additional consumer thread. If the producer thread need to share data to consumers ready thread, using the queue way to pass data, it can easily solve data sharing problems between them. But if producers and consumers in a certain period of time, the situation does not match the data processing speed of the event happen? Ideally, if the rate of producer output data is greater than the rate of consumer spending, and when the cumulative production data out to a certain extent, then the producer must pause to wait for it (blocking producer thread), in order to wait for consumers thread the accumulated data is processed, and vice versa. However, before the concurrent release package, in a multithreaded environment, we have to own every programmer to control these details, in particular, but also on the efficiency and thread-safe, and this will give our program is not a small degree of complexity . Fortunately, this time, a strong concurrent package turned out, but he also gives us a powerful BlockingQueue. (In a multithreaded areas: the so-called blocking, in some cases hung threads (ie blocked), once the conditions are met, the suspended thread will be woken up automatically).

4. The following illustration shows two BlockingQueue two common blocking scenarios:

4.1.ArrayBlockingQueue: There is a blocking queue borders, its internal implementation is an array. There is meaning boundary its capacity is limited, we have to specify the size of its capacity at the time of its initialization, the capacity of the specified size once it is immutable. ArrayBlockingQueue is FIFO stored data, newly inserted object is the tail, the latest object is removed from the head. Here is an example of an initialization and use ArrayBlockingQueue:

ArrayBlockingQueue<String> arrays = new ArrayBlockingQueue<String>(3);
	arrays.add("李四");
	 arrays.add("张军");
	arrays.add("张军");
	// 添加阻塞队列
	arrays.offer("张三", 1, TimeUnit.SECONDS);

4.2.LinkedBlockingQueue blocking queue size configuration is optional, if we specify a size when initialized, it is bounded, if not specified, it is borderless. He said to be borderless, in fact, is the use of a default size of Integer.MAX_VALUE capacity. Its internal implementation is a linked list.

And ArrayBlockingQueue Like, LinkedBlockingQueue also store data in a FIFO manner, the newly inserted object is the tail, the latest object is removed from the head. The following is an example of initialization and to make the LinkedBlockingQueue:

LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue(3);
linkedBlockingQueue.add("张三");
linkedBlockingQueue.add("李四");
linkedBlockingQueue.add("李四");
System.out.println(linkedBlockingQueue.size());

4.3.PriorityBlockingQueue is not a queue borders, its collation and java.util.PriorityQueue same. Note PriorityBlockingQueue permit insertion of null objects. All objects inserted PriorityBlockingQueue java.lang.Comparable must implement the interface, queue priority is in accordance with the rules of the sort we realize this interface to define. In addition, we can get an iterator Iterator from PriorityBlockingQueue, but this does not guarantee that the iterator along in accordance with the priority.

4.4. Code (use BlockingQueue to simulate producers and consumers )

class ProducerThread extends Thread {
    private BlockingQueue queue;
    private volatile boolean flag = true;
    private static AtomicInteger count = new AtomicInteger();
    ProducerThread(BlockingQueue blockingQueue) {
        this.queue = blockingQueue;
    }
    @Override
    public void run() {
        System.out.println("生产者线程启动...");
        try {
            while (flag) {
                System.out.println("正在生产队列");
                String data = count.incrementAndGet() + "";
                // 添加队列
                boolean offer = queue.offer(data);
                if (offer) {
                    System.out.println("生产者添加队列" + data + "成功!");
                } else {
                    System.out.println("生产者添加队列" + data + "失败!");
                }
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            System.out.println("生产者线程停止...");
        }
    }
    public void stopThread() {
        this.flag = false;
    }
}
class ConsumerThread extends Thread {
    private BlockingQueue queue;
    private volatile boolean flag = true;

    ConsumerThread(BlockingQueue blockingQueue) {
        this.queue = blockingQueue;
    }
    @Override
    public void run() {
        System.out.println("消费者线程启动....");
        try {
            while (flag) {
                // 获取完毕,队列会删除掉
                String data = (String) queue.poll(2, TimeUnit.SECONDS);
                if (data != null) {
                    System.out.println("消费者获取 data:" + data + "成功...");
                } else {
                    System.out.println("消费者获取 data:" + data + "失敗..");
                    this.flag = false;
                }
            }
        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            System.out.println("消费停止....");
        }
    }
}
public class Test006 {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> queue = new LinkedBlockingQueue<String>(10);
        ProducerThread p1 = new ProducerThread(queue);
        // ProducerThread p2 = new ProducerThread(queue);
        ConsumerThread c1 = new ConsumerThread(queue);
        p1.start();
        // p2.start();
        c1.start();
        // 执行10s
        Thread.sleep(10 * 1000);
        p1.stopThread();
        // p2.stopThread();
    }
}

4.4 Results

生产者线程启动...
正在生产队列
消费者线程启动....
生产者添加队列1成功!
消费者获取 data:1成功...
正在生产队列
生产者添加队列2成功!
消费者获取 data:2成功...
正在生产队列
生产者添加队列3成功!
消费者获取 data:3成功...
正在生产队列
生产者添加队列4成功!
消费者获取 data:4成功...
正在生产队列
生产者添加队列5成功!
消费者获取 data:5成功...
正在生产队列
生产者添加队列6成功!
消费者获取 data:6成功...
正在生产队列
生产者添加队列7成功!
消费者获取 data:7成功...
正在生产队列
生产者添加队列8成功!
消费者获取 data:8成功...
正在生产队列
生产者添加队列9成功!
消费者获取 data:9成功...
正在生产队列
生产者添加队列10成功!
消费者获取 data:10成功...
生产者线程停止...
消费者获取 data:null失敗..
消费停止....

Fourth, the end of the

Always  keep  the faith!!! 

Published 122 original articles · won praise 64 · views 50000 +

Guess you like

Origin blog.csdn.net/chenmingxu438521/article/details/103833647