1.并发编程挑战-上下文切换
并行和串行执行
package com.qdb.thinkv.thread.base; /** * 问题:多线程一定快吗?不一定,通过调整 count分别设置 比如1w 和 1亿 进行比较 * 思考:如何减少上下文切换? */ public class ConcurrencyTest { public static final long count=1000000000L; public static void main(String[] args) throws InterruptedException { concurrency(); seriai(); } public static void concurrency() throws InterruptedException{ long start=System.currentTimeMillis(); Thread thread=new Thread(new Runnable(){ public void run() { int a=0; for (long i = 0; i < count; i++) { a+=5; } } }); thread.start(); int b=0; for (long i = 0; i < count; i++) { b--; } thread.join(); long time=System.currentTimeMillis()-start; System.out.println("concurrency"+time+"ms,b="+b); } public static void seriai(){ long start=System.currentTimeMillis(); int a=0; for (long i = 0; i < count; i++) { a+=5; } long time=System.currentTimeMillis()-start; System.out.println("seriai"+time+"ms,a="+a); start=System.currentTimeMillis(); int b=0; for (long i = 0; i < count; i++) { b--; } time=System.currentTimeMillis()-start; System.out.println("seriai"+time+"ms,b="+b+",a="+a); } }
总结:线程有创建和上下文切换的开销。
减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。
1.无锁并发编程。
多线程竞争锁时,会引起上下文切换,多线程处理数据时,可以用一些办法来避免使用锁。如数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据。
2.cas算法。
java 的atomic包使用cas算法来更新数据,不需要加锁。
3.使用最少的线程。
避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态。
4.协程
在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。