Java Concurrency: Thread limit


You Rui lesson takes you learn about Java concurrency issues and more information on the thread limit.

In this article, we will explore the thread limit, its meaning and how to implement. So let us study it directly.


Thread limit

Most concurrency problem occurs only when we want to share variables or variable state variable between threads. If the shared mutable state among multiple threads, all threads will be able to read and modify the values ​​of the state, resulting in errors or unexpected behavior. One way to avoid this problem is to simply not share data between threads. This technique is referred to thread limit, it is one of the easiest way to achieve thread-safe in our application.


Java language does not have any method of execution threads restrictions. Thread limit is achieved by way of the design process, the program state is not allowed to use a plurality of threads, so to force the implementation. There are several types of thread limit, as described below.


Temporary thread limit

Temporary restrictions thread describes a thread limitation, the co-responsibility of the developer or group of developers of the program is responsible to ensure that the object of use is limited to a single thread. This method is very fragile, and in most cases should be avoided.


Ad-hoc a special case of the thread restrictions apply to volatile variables. Just make sure only write from a single thread volatile variables, you can share the volatile variable performs a read - modify - write operation. In this case, you will modify the limit in a single thread, so as to prevent race conditions, and ensure the visibility of the volatile variables ensure that other threads to see the latest value.


Stack limit

Stack limit is limited to a variable or object thread's stack. This thread is much stronger than the temporary constraint, since the state by defining variables in the stack itself, it even further limit the scope of the object. For example, consider the following code:

private long numberOfPeopleNamedJohn(List<Person> people) {
  List<Person> localPeople = new ArrayList<>();
  localPeople.addAll(people);
  return localPeople.stream().filter(person -> person.getFirstName().equals("John")).count();
}

 

In the above code, we passed a list of people, but did not use it directly. On the contrary, we have to create your own list, which is located in a local thread currently executing and add to all the people localPeoplein. Since we only numberOfPeopleNamedJohndefine the list of methods, so that the variable localPeoplestack is limited, because it exists in a thread's stack, and therefore can not be accessed by any other thread. This allows localPeoplethread-safe. Our only caveat is that we should not allow localPeopleto escape the scope of this method is to keep it within the stack limit. When you define this variable, the variable should be recorded or comments, generally speaking, only the current developers in order to avoid the use of this variable, in the future, another developer might screw up.


Thread Local

ThreadLocalAllows you to value objects associated with the value of each thread holds. It allows you a different for different thread storage object and which object corresponds to which maintenance thread. It has set and get accessor method to use it each thread to maintain a separate copy of the value. get()Method always returns transferred from the currently executing thread to the set()latest value. Let's look at an example:

public class ThreadConfinementUsingThreadLocal {
    public static void main(String[] args) {
        ThreadLocal<String> stringHolder = new ThreadLocal<>();
        Runnable runnable1 = () -> {
            stringHolder.set("Thread in runnable1");
            try {
                Thread.sleep(5000);
                System.out.println(stringHolder.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable runnable2 = () -> {
            stringHolder.set("Thread in runnable2");
            try {
                Thread.sleep(2000);
                stringHolder.set("string in runnable2 changed");
                Thread.sleep(2000);
                System.out.println(stringHolder.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable runnable3 = () -> {
            stringHolder.set("Thread in runnable3");
            try {
                Thread.sleep(5000);
                System.out.println(stringHolder.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Thread thread1 = new Thread(runnable1);
        Thread thread2 = new Thread(runnable2);
        Thread thread3 = new Thread(runnable3);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

 


在上面的示例中,我们使用相同的ThreadLocal对象stringHolder执行了三个线程。如你在这里看到的,首先,我们在stringHolder对象的每个线程中设置一个字符串,使其包含三个字符串。然后,经过一些暂停后,我们仅从第二个线程更改了该值。下面是程序的输出:

string in runnable2 changed
Thread in runnable1
Thread in runnable3

 

如你在上面的输出中看到的,线程2的字符串已更改,但线程1和线程3的字符串未受影响。如果在从ThreadLocal获取特定线程上的值之前未设置任何值,则它将返回null。终止线程后,ThreadLocal中特定于线程的对象将准备进行垃圾回收。


这就是关于线程限制的全部内容。我希望该博客对你有所帮助,并且你必须学习新的知识。

谢谢,祝你愉快!

更多技术点探讨欢迎留言或私信!

 抽丝剥茧 细说架构那些事——【优锐课】

Guess you like

Origin blog.51cto.com/14631216/2462702