一、上下文切换
多线程上下文切换
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);
}
}
}