多线程常见知识

一、上下文切换
多线程上下文切换
https://www.cnblogs.com/szlbm/p/5505707.html
《Java并发编程的艺术》
即使是单核CPU也支持多线程执行代码,CPU通过给给个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间非常短,CPU通过不停的切换线程执行,让我们感觉多个线程同时执行的。
CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再次加载这个任务的状态,从任务保存到再加载的过程就是一次上下文切换。

如何减少上下文切换
既然上下文切换会导致额外的开销,因此减少上下文切换次数便可以提高多线程程序的运行效率。减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。
1、无锁并发编程。多线程竞争时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash取模分段,不同的线程处理不同段的数据
2、CAS算法。Java的Atomic包使用CAS算法来更新数据,而不需要加锁
3、使用最少线程。避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态
4、协程。在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换

Java线程之间如何通信
1、join() 在线程B中调用线程A.join()方法
可以实现线程A执行完,线程B再执行
2、Object类中的wait(),notify()方法,参考生产者消费者线程

/**
 * This code is explanation for article:
 */
public class ForArticle {

    public static void main(String[] args) {
//        demo1();
        //demo2();
        demo3();

    }

    /**
     * random output
     */
    private static void demo1() {
        Thread A = new Thread(new Runnable() {
            @Override
            public void run() {
                printNumber("A");
            }
        });

        Thread B = new Thread(new Runnable() {
            @Override
            public void run() {
                printNumber("B");
            }
        });

        A.start();

        B.start();
    }

    /**
     * A 1, A 2, A 3, B 1, B 2, B 3
     */
    private static void demo2() {
        Thread A = new Thread(new Runnable() {
            @Override
            public void run() {
                printNumber("A");
            }
        });

        Thread B = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("B 开始等待 A");
                try {
                    A.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                printNumber("B");
            }
        });

        A.start();
        B.start();
    }

    /**
     * A 1, B 1, B 2, B 3, A 2, A 3
     */
    private static void demo3() {
        Object lock = new Object();

        Thread A = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("INFO: A 等待锁");
                synchronized (lock) {
                    System.out.println("INFO: A 得到了锁 lock");
                    System.out.println("A 1");
                    try {
                        System.out.println("INFO: A 准备进入等待状态,调用 lock.wait() 放弃锁 lock 的控制权");
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("INFO: 有人唤醒了 A, A 重新获得锁 lock");
                    System.out.println("A 2");
                    System.out.println("A 3");
                }

            }
        });

        Thread B = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("INFO: B 等待锁");
                synchronized (lock) {
                    System.out.println("INFO: B 得到了锁 lock");
                    System.out.println("B 1");
                    System.out.println("B 2");
                    System.out.println("B 3");

                    System.out.println("INFO: B 打印完毕,调用 lock.notify() 方法");
                    lock.notify();
                }
            }
        });
        A.start();
        B.start();

    }

    private static void printNumber(String threadName) {
        int j=0;
        while (j++ < 3) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(threadName + " print: " + j);
        }
    }

}

猜你喜欢

转载自blog.csdn.net/qq_31617121/article/details/81139572