Use the join() method
In many cases, the main thread to generate and starting the child thread, if the child thread to be a lot of time consuming operations, the main thread will often ended before the child thread, but if the main thread after handling the affairs of the other, need to use the child thread processing result, which is the main thread needs to wait for the child thread completes before the end, This is where the join() method comes in. In addition, the join() method is also used when one thread is waiting for another.
The join method causes the thread x to execute the run() task normally, while the current thread Z blocks and waits for thread X to destroy before continuing to execute the code following thread Z.
class MyThread extends Thread{
@Override
public void run(a) {
try {
int secondVal=(int) (Math.random()*10000);
System.out.println(secondVal);
Thread.sleep(secondVal);
} catch(InterruptedException e) { e.printStackTrace(); }}}public class Run {
public static void main(String[] args) {
try {
MyThread t=new MyThread();
t.start();
t.join();
System.out.println("Statements that are executed after the MyThread object has finished executing");
} catch(InterruptedException e) { e.printStackTrace(); }}}Copy the code
Running results:
4139 Statement that is executed after the MyThread object has finished executingCopy the code
That is, the Main thread blocks when t executes to t.in () and does not continue executing until t completes.
The join() method has the effect of queuing threads to run, similar to synchronization. Join differs from synchronized in that a JOIN uses the wait() method internally, while the synchronized keyword uses the “object monitor.” The core logic of the join() method is:
while (isAlive()) {
wait(0);
}
Copy the code
The notifyAll() method is called after the join thread completes, and is called in the JVM implementation.
The join() method encounters an interrupt() method.
The argument in join(long) sets the wait time. Unlike sleep(long), join(long) is implemented internally using wait(long), so the join method releases the lock, while sleep does not.
Use ThreadLocal
Variable values can be shared using the form of a public static variable, which is used by all threads. The JDK provides a ThreadLocal class that allows each thread to bind its own value. The ThreadLocal class can be compared to a box that stores the private data of each thread and implements the function of local storage.
Sample code:
class Tool{
public static ThreadLocal threadLocal=new ThreadLocal();
}
class ThreadA extends Thread{
@Override
public void run(a) {
try {
for(int i=0; i<5; i++){ Tool.threadLocal.set("ThreadA"+i);
System.out.println("ThreadA get value: "+Tool.threadLocal.get());
Thread.sleep(200); }}catch(InterruptedException e) { e.printStackTrace(); }}}class ThreadB extends Thread{
@Override
public void run(a) {
try {
for(int i=0; i<6; i++){ Tool.threadLocal.set("ThreadB"+i);
System.out.println("ThreadB get value: "+Tool.threadLocal.get());
Thread.sleep(200); }}catch(InterruptedException e) { e.printStackTrace(); }}}public class Run {
public static void main(String[] args) throws InterruptedException {
ThreadA a=new ThreadA();
ThreadB b=new ThreadB();
a.start();
b.start();
for(int i=0; i<4; i++){ Tool.threadLocal.set("Main"+i);
System.out.println("Main get value: "+Tool.threadLocal.get());
Thread.sleep(200); }}}Copy the code
The running results are as follows:
ThreadA get value: ThreadA0
ThreadB get value: ThreadB0
Main get value: Main0
ThreadA get value: ThreadA1
ThreadB get value: ThreadB1
Main get value: Main1
ThreadA get value: ThreadA2
ThreadB get value: ThreadB2
Main get value: Main2
ThreadA get value: ThreadA3
ThreadB get value: ThreadB3
Main get value: Main3
ThreadB get value: ThreadB4
ThreadA get value: ThreadA4
ThreadB get value: ThreadB5
Copy the code
As you can see, different ranges of I are set for the three threads, but the values obtained by each thread are corresponding. The ThreadLocal class allows variables to be isolated between threads. Values from different threads can be stored in the ThreadLocal class.
In addition, you can set initialValue() to set the initialValue so that get() does not return null.
public class ThreadLocalExt extends ThreadLocal {
@Override
protected Object initialValue(a) {
return "I'm the default for the first time get is no longer null."; }}Copy the code
Each Thread has a ThreadLocal ThreadLocalMap object. When we call a ThreadLocal set(T value) method, we get the ThreadLocalMap object of the current thread and insert the ThreadLocal->value key-value pair into the Map. ThreadLocal is not technically designed to solve the problem of multithreaded concurrency, because there is no multithreaded competition.
In some scenes, especially using a thread pool), because the ThreadLocal. ThreadLocalMap the underlying data structure, leading to a ThreadLocal has a memory leak, should as far as possible after each use ThreadLocal manually call remove (), To avoid the classic risk of ThreadLocal leaking memory or even disrupting its own business.
InheritableThreadLocal
Use the InheritableThreadLocal class to get values inherited from the parent thread in the child thread.
class InheritableThreadLocalExt extends InheritableThreadLocal{
@Override
protected Object initialValue(a) {
return new Date().getTime();
}
@Override
protected Object childValue(Object parentValue) {
return parentValue+" tail"; }}class Tools{
public static InheritableThreadLocalExt t1=new InheritableThreadLocalExt();
}
class ThreadA extends Thread{
@Override
public void run(a) {
try {
for(int i=0; i<5; i++){ System.out.println("Value in ThreadA:"+Tools.t1.get());
Thread.sleep(100); }}catch(InterruptedException e) { e.printStackTrace(); }}}public class Run {
public static void main(String[] args) {
try {
for(int i=0; i<5; i++){ System.out.println("In Main:"+Tools.t1.get());
Thread.sleep(100);
}
Thread.sleep(5000);
ThreadA a=new ThreadA();
a.start();
} catch(InterruptedException e) { e.printStackTrace(); }}}Copy the code
Running results:
In Main: 1544438516856 In Main: 1544438516856 In Main: 1544438516856 In Main: 1544438516856 In Main: 1544438516856 1544438516856 In ThreadA Value: 1544438516856 tail In ThreadA value: 1544438516856 tail in ThreadA value: 1544438516856 tail in ThreadA value: 1544438516856 1544438516856 tail Value in ThreadA: 1544438516856 tailCopy the code
As you can see, the ThreadA thread was called from the Main thread, and the ThreadA thread successfully fetched the value from the Main thread and modified it with the childValue() method.
The resources
- Gao Hongyan. Java Multi-threaded Programming Core Technology [M]. China Machine Press, 2015
- Blog.csdn.net/qq_34337272…
- Github.com/CyC2018/CS-…