Java multi-threading learning (e) inter-thread communication knowledge supplement

mind Mapping:
Here Insert Picture Description

A pipeline input / output streams

Feed line input / output stream and the normal file / network input or output stream, the output stream is different in that the pipe input / output streams is mainly used for data transmission between the threads , and the transmission medium is a memory .

Pipeline input / output streams include the following two types of implement:

Byte-oriented: the PipedOutputStream, the PipedInputStream

Character-oriented: PipedWriter, PipedReader

1.1 a first conduit input / output streams Examples

The complete code: https://github.com/Snailclimb/threadDemo/tree/master/src/pipedInputOutput
writeMethod method

    public void writeMethod(PipedOutputStream out) {
        try {
            System.out.println("write :");
            for (int i = 0; i < 300; i++) {
                String outData = "" + (i + 1);
                out.write(outData.getBytes());
                System.out.print(outData);
            }
            System.out.println();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

readMethod method

    public void readMethod(PipedInputStream input) {
        try {
            System.out.println("read  :");
            byte[] byteArray = new byte[20];
            int readLength = input.read(byteArray);
            while (readLength != -1) {
                String newData = new String(byteArray, 0, readLength);
                System.out.print(newData);
                readLength = input.read(byteArray);
            }
            System.out.println();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Test Methods

    public static void main(String[] args) {

        try {
            WriteData writeData = new WriteData();
            ReadData readData = new ReadData();

            PipedInputStream inputStream = new PipedInputStream();
            PipedOutputStream outputStream = new PipedOutputStream();

            // inputStream.connect(outputStream);
            outputStream.connect(inputStream);

            ThreadRead threadRead = new ThreadRead(readData, inputStream);
            threadRead.start();

            Thread.sleep(2000);

            ThreadWrite threadWrite = new ThreadWrite(writeData, outputStream);
            threadWrite.start();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

We define the above two methods writeMethod and readMethod, the former is used to write bytes / characters (depending on your use is PipedOuputStream or PipedWriter ), which is used to read bytes / characters (depending on your use is PipedInputStream or PipedReader ). we defined two threads threadRead and threadWrite , threadRead thread running readMethod method, threadWrite run writeMethod method. Then ** outputStream.connect (inputStream) or inputStream.connect (outputStream) ** link the two conduit flow generation, so that data can be input and output.

Two Thread.join () use

In many cases, the main thread to create and start a child thread, if the child thread to a lot of time-consuming operation, often before the child thread the main thread will end, but if the main thread has finished the deal with other matters, need to deal with the results of the sub-thread, which is the main thread needs to wait longer after the end of sub-thread execution is completed, we should use this time to join () method has. In addition, a thread needs to wait for another thread also need to use the join () method.

Thread class addition to join () method , but also provides a ** join (long millis), join (long millis, int nanos) ** timeout feature of having two methods. Both methods indicate a timeout, if the thread thread does not terminate in the specified timeout period, it will be returned from the timeout method.

2.1 join method

Do not use the join method of presentation drawbacks:

public class Test {

    public static void main(String[] args) throws InterruptedException {

        MyThread threadTest = new MyThread();
        threadTest.start();

        //Thread.sleep(?);//因为不知道子线程要花的时间这里不知道填多少时间
        System.out.println("我想当threadTest对象执行完毕后我再执行");
    }
    static public class MyThread extends Thread {

        @Override
        public void run() {
            System.out.println("我想先执行");
        }

    }
}

You can see the child thread has been executed, the example here is just a simple demonstration, we think about: If the fruit is the thread running the main thread needs to run how to do? sleep method? Of course you can, but the time the child thread needs to run is uncertain, so sleep How long course, also uncertain. Here it is necessary to use the join method to solve the above problems.

Use join method to solve the above problem:
Test.java

public class Test {

    public static void main(String[] args) throws InterruptedException {

        MyThread threadTest = new MyThread();
        threadTest.start();

        //Thread.sleep(?);//因为不知道子线程要花的时间这里不知道填多少时间
        threadTest.join();
        System.out.println("我想当threadTest对象执行完毕后我再执行");
    }
    static public class MyThread extends Thread {

        @Override
        public void run() {
            System.out.println("我想先执行");
        }

    }
}

The above code is just an added: threadTest.join () ;. Here the role of the join method is the main thread needs to wait longer after the end of sub-thread execution is completed.

Use 2.2 join (long millis) method

Parameters (long millis) is set to join the waiting time.

JoinLongTest.java

public class JoinLongTest {

    public static void main(String[] args) {
        try {
            MyThread threadTest = new MyThread();
            threadTest.start();

            threadTest.join(2000);// 只等2秒
            //Thread.sleep(2000);

            System.out.println("  end timer=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static public class MyThread extends Thread {

        @Override
        public void run() {
            try {
                System.out.println("begin Timer=" + System.currentTimeMillis());
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

Whether running threadTest.join (2000) or Thread.sleep (2000), "end timer = 1522036620288" output statements are lapsing two seconds, "end timer = 1522036620288" statement after the output of the program will run for a period of time, because run method thread has Thread.sleep (10000) statements.

In addition threadTest.join (2000) and Thread.sleep (2000) and the difference is: Thread.sleep (2000) does not release the lock, threadTest.join (2000) will release the lock.

Three ThreadLocal use

Shared values of variables can be used in the form of public static variables, all threads are using a public static variable. If you want to implement each thread has its own shared variable how to solve it? JDK provided ThreadLocal class in order to solve this problem. ThreadLocal class main solution is to allow each thread to bind their value, ThreadLocal class image of the metaphor of the box can store data, the box can store private data for each thread.

As another simple example:
For example, there are two people to collect treasure treasure house, the two share a bag of words will certainly have a dispute, but both of them assigned to a bag, then it will not be such a problem for everyone. If these two people compared to the thread, then ThreadLocal is for the two threads of competition.

Related methods ThreadLocal class:
Method Name Description
get (Returns a copy of the current value of this thread-local thread in).
set (T value) will be set to the value specified copy the current thread of this thread-local variable
value remove () to delete this thread-local variables of the current thread.
"initial value" the initialValue () Returns the current thread-local variable thread

3.1 ThreadLocal class of first test

public class Test1 {
    public static ThreadLocal<String> t1 = new ThreadLocal<String>();

    public static void main(String[] args) {
        if (t1.get() == null) {
            System.out.println("为ThreadLocal类对象放入值:aaa");
            t1.set("aaaֵ");
        }
        System.out.println(t1.get());//aaa
        System.out.println(t1.get());//aaa
    }

}

As seen from the results of operation, the first call ThreadLocal object get () method the value returned is null, by calling the method set () can be assigned ThreadLocal object.

If you want to solve the problem get () method null, you can use ThreadLocal object initialValue method . as follows:


public class Test2 {
    public static ThreadLocalExt t1 = new ThreadLocalExt();

    public static void main(String[] args) {
        if (t1.get() == null) {
            System.out.println("从未放过值");
            t1.set("我的值");
        }
        System.out.println(t1.get());
        System.out.println(t1.get());
    }
    static public class ThreadLocalExt extends ThreadLocal {
        @Override
        protected Object initialValue() {
            return "我是默认值 第一次get不再为null";
        }
    }


}

Between 3.2 validation thread variable isolation
Test3.java

/**
 *TODO 验证线程变量间的隔离性
 */
public class Test3 {

    public static void main(String[] args) {
        try {
            for (int i = 0; i < 10; i++) {
                System.out.println("       在Main线程中取值=" + Tools.tl.get());
                Thread.sleep(100);
            }
            Thread.sleep(5000);
            ThreadA a = new ThreadA();
            a.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    static public class Tools {
        public static ThreadLocalExt tl = new ThreadLocalExt();
    }
    static public class ThreadLocalExt extends ThreadLocal {
        @Override
        protected Object initialValue() {
            return new Date().getTime();
        }
    }

    static public class ThreadA extends Thread {

        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("在ThreadA线程中取值=" + Tools.tl.get());
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
}

The results can be seen running from the child and the parent thread threads each have their own value.

3.3 InheritableThreadLocal

ThreadLocal class is good, but the child thread does not take the class ThreadLocal variable to the parent thread, InheritableThreadLocal class is to solve this problem.

Take the value of the parent thread:

Tools Test3.java modified internal classes and ThreadLocalExt categories as follows:

 static public class Tools {
        public static InheritableThreadLocalExt tl = new InheritableThreadLocalExt();
    }
    static public class InheritableThreadLocalExt extends InheritableThreadLocal {
        @Override
        protected Object initialValue() {
            return new Date().getTime();
        }
    }

Take and modify the value of the parent thread:

Tools Test3.java modified internal classes and InheritableThreadLocalExt categories as follows:

    static public class Tools {
        public static InheritableThreadLocalExt tl = new InheritableThreadLocalExt();
    }
    static public class InheritableThreadLocalExt extends InheritableThreadLocal {
        @Override
        protected Object initialValue() {
            return new Date().getTime();
        }

        @Override
        protected Object childValue(Object parentValue) {
            return parentValue + " 我在子线程加的~!";
        }
    }

In use InheritableThreadLocal class thing to note is: If the child thread in obtaining the value of the main thread in the value InheritableThreadLocal make changes, then the child thread was taken to the old values.

Address reprint: https://blog.csdn.net/qq_34337272/article/details/79694226

Guess you like

Origin blog.csdn.net/weixin_39940206/article/details/94396356