清华扫地僧整理的全网最全多线程详解,看完怀疑自己的认知( 五 )

运行结果:

清华扫地僧整理的全网最全多线程详解,看完怀疑自己的认知

文章插图
 
从图中可以看出,程序既无法向下执行,也不会抛出任何异常,就一直“僵持”着 。究其原因,是因为:上面程序中A对象和B对象的方法都是同步方法,也就是A对象和B对象都是同步锁 。程序中两个线程执行,副线程的线程执行体是 DeadLock类的run()方法,主线程的线程执行体是 Deadlock的main()方法(主线程调用了init()方法) 。其中run()方法中让B对象调用b进入foo()方法之前,该线程对A对象加锁—当程序执行到①号代码时,主线程暂停200ms:CPU切换到执行另一个线程,让B对象执行bar()方法,所以看到副线程开始执行B实例的bar()方法,进入bar()方法之前,该线程对B对象加锁——当程序执行到②号代码时,副线程也暂停200ms:接下来主线程会先醒过来,继续向下执行,直到③号代码处希望调用B对象的last()方法——执行该方法之前必须先对B对象加锁,但此时副线程正保持着B对象的锁,所以主线程阻塞;接下来副线程应该也醒过来了,继续向下执行,直到④号代码处希望调用A对象的 last()方法——执行该方法之前必须先对A对象加锁,但此时主线程没有释放对A对象的锁——至此,就出现了主线程保持着A对象的锁,等待对B对象加锁,而副线程保持着B对象的锁,等待对A对象加锁,两个线程互相等待对方先释放,所以就出现了死锁 。
六、线程池系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互 。在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池 。
与数据库连接池类似的是,线程池在系统启动时即创建大量空闲的线程,程序将一个 Runnable对象或 Callable对象传给线程池,线程池就会启动一个空闲的线程来执行它们的run()或call()方法,当run()或call()方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的run()或call()方法 。
创建线程池的几个常用的方法:
1.newSingleThreadExecutor创建一个单线程的线程池 。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务 。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它 。此线程池保证所有任务的执行顺序按照任务的提交顺序执行 。
2.newFixedThreadPool创建固定大小的线程池 。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小 。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程 。
3.newCachedThreadPool创建一个可缓存的线程池 。如果线程池的大小超过了处理任务所需要的线程,
那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务 。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小 。
4.newScheduledThreadPool创建一个大小无限的线程池 。此线程池支持定时以及周期性执行任务的需求 。
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors; public class ThreadPoolTest {public static void main(String[] args) {ExecutorService pool=Executors.newFixedThreadPool(6);Runnable target=()->{for(int i=0;i<10;i++) {System.out.println(Thread.currentThread().getName()+"的i的值"+i);}};pool.submit(target);pool.submit(target);pool.submit(target);//关闭线程池pool.shutdown();} }运行结果:
pool-1-thread-1的i的值0pool-1-thread-2的i的值0pool-1-thread-3的i的值0pool-1-thread-2的i的值1pool-1-thread-1的i的值1pool-1-thread-2的i的值2pool-1-thread-3的i的值1pool-1-thread-2的i的值3pool-1-thread-1的i的值2pool-1-thread-2的i的值4pool-1-thread-3的i的值2pool-1-thread-2的i的值5pool-1-thread-1的i的值3pool-1-thread-2的i的值6pool-1-thread-3的i的值3pool-1-thread-2的i的值7pool-1-thread-1的i的值4pool-1-thread-2的i的值8pool-1-thread-3的i的值4pool-1-thread-2的i的值9pool-1-thread-1的i的值5pool-1-thread-3的i的值5pool-1-thread-1的i的值6pool-1-thread-1的i的值7pool-1-thread-1的i的值8pool-1-thread-1的i的值9pool-1-thread-3的i的值6pool-1-thread-3的i的值7pool-1-thread-3的i的值8pool-1-thread-3的i的值9后记怎么样?来自清华扫地僧的功力如此深厚,想了解是哪位吗?那就请多多留言评论,或者关注小编,私信回复【学习】,即可免费获赠清华大佬海量学习资料 。


推荐阅读