Java thread communication in several ways

Foreword

When concurrent programming will inevitably encounter communication problems between the thread of a multithreaded. Ideological thread communication is generally divided into two types: shared and passed .

Thread communication

Share implementations can be shared variable, share files, databases, networks and so on. Implementations may be transmitted message queue, producer - consumer model, etc., and these two kinds of communication is not absolutely independent, such as producer - consumer model can be seen as a shared memory area.
For sharing, the easiest way than the shared variable. There is such a question:

Two threads alternating odd and even print?

This question is the main test sites: How to inter-thread communication? A thread after a print, how to notify another thread print, this cycle, the final effect is alternately print.

Shared variables

Use shared variables, this can be achieved

public class ThreadDemo {

    // 共享变量,线程运行标识
    private static volatile Boolean odd = true;
    private static int number = 1;

    public static void main(String[] args) throws Exception {
        // 奇数
        Thread threadOdd = new Thread(() -> {
            while (number <= 10) {
                while (odd) {
                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;
                    odd = false;
                }
            }
        });

        // 偶数
        Thread threadEven = new Thread(() -> {
            while (number <= 10) {
                while (!odd) {
                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;
                    odd = true;
                }
            }
        });

        threadOdd.start();
        threadEven.start();
    }
}

Output

Thread-0:1
Thread-1:2
Thread-0:3
Thread-1:4
Thread-0:5
Thread-1:6
Thread-0:7
Thread-1:8
Thread-0:9
Thread-1:10

wait/notify

If you use a wait/notifymechanism to achieve, the following code:

public class ThreadDemo {

    private static int number = 1;
    private static final Object object = new Object();

    public static void main(String[] args) throws Exception {
        // 奇数
        Thread threadOdd = new Thread(() -> {
            synchronized (object) {
                while (number <= 10) {
                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;
                    try {
                        object.notify();
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 终止程序
                object.notify();
            }
        });

        // 偶数
        Thread threadEven = new Thread(() -> {
            synchronized (object) {
                while (number <= 10) {
                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;
                    try {
                        object.notify();
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 终止程序
                object.notify();
            }
        });

        threadOdd.start();
        threadEven.start();
    }
}

Results are as follows:

Thread-0:1
Thread-1:2
Thread-0:3
Thread-1:4
Thread-0:5
Thread-1:6
Thread-0:7
Thread-1:8
Thread-0:9
Thread-1:10

wait / notify improvement

The first two methods although correct operating results, but can not guarantee an odd thread must run first.
To ensure an odd number of threads to run, the above code can be slightly modified to look to wait/notifyas an example:

/**
 * @author sicimike
 */
public class ThreadDemo {

    private static int number = 1;
    private static final Object object = new Object();
    final static CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) {
        // 奇数线程
        Thread threadOdd = new Thread(() -> {
            synchronized (object) {
                latch.countDown();
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + " : " + number++);
                    try {
                        object.notify();
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                object.notify();
            }
        });

        // 偶数线程
        Thread threadEven = new Thread(() -> {
            try {
                latch.await();
                synchronized (object) {
                    for (int i = 0; i < 5; i++) {
                        System.out.println(Thread.currentThread().getName() + " : " + number++);
                        object.notify();
                        object.wait();
                    }
                    object.notify();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        threadOdd.start();
        threadEven.start();
    }
}

With CountDownLatchclass can easily achieve the odd threads to run.

LockSupport Tools

LockSupportTools in the suspend / resume, wait / notify, park / unpark has been explained in detail, not repeat them here.

In this example, but also ensures the implementation of the first odd thread

/**
 * @author sicimike
 */
public class ThreadDemo {

    private static int number = 1;
    private static Thread threadOdd = null;
    private static Thread threadEven = null;

    public static void main(String[] args) {
        // 奇数线程
        threadOdd = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " : " + number++);
                // 唤醒threadEven线程
                LockSupport.unpark(threadEven);
                // 阻塞当前线程
                LockSupport.park();
            }
        });

        // 偶数线程
        threadEven = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
            	// 阻塞threadEven,使threadOdd先运行
                LockSupport.park();
                System.out.println(Thread.currentThread().getName() + " : " + number++);
                // 唤醒threadOdd线程
                LockSupport.unpark(threadOdd);
            }
        });

        threadOdd.start();
        threadEven.start();
    }
}

Results of the

Thread-0 : 1
Thread-1 : 2
Thread-0 : 3
Thread-1 : 4
Thread-0 : 5
Thread-1 : 6
Thread-0 : 7
Thread-1 : 8
Thread-0 : 9
Thread-1 : 10

Epilogue

Sometimes the program results are correct, it does not mean the program is entirely correct, especially when it comes to multi-threaded code. As the above code is wrong, please let me know.

发布了52 篇原创文章 · 获赞 107 · 访问量 1万+

Guess you like

Origin blog.csdn.net/Baisitao_/article/details/100062949