ThreadPool线程池使用及解决主线程和子线程执行顺序问题

 线程池创建五个线程,每个线程往list中添加100个元素。synchronized只锁线程共享变量list对象,代码段内仅添加元素及打印信息。设置10ms睡眠时间给其余线程机会。

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
//list是所有线程共享变量需要加锁避免冲突
final List list = new ArrayList();
for(int i=0;i<5;i++) {
    fixedThreadPool.execute(new Runnable() {
	@Override
	public void run() {
    //j是线程内部变量,每个线程都有一份,自己会管理,不会冲突
	    int j=100;
		while(j>0) {
		    try {
			    Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		    synchronized (list) {
			    list.add(j);
			    System.out.println(Thread.currentThread().getName()+"---------"+list.size());
			    j--;
		    }

		}
	}
	});
}
fixedThreadPool.shutdown();
//这里的sysout输出是在main线程中的,其list的size根据当时这个list的情况只输出一次,可能是任意小于500的值
System.out.println(Thread.currentThread().getName()+"---------"+list.size());

输出结果:(注意这里的main-----0  这个值是fixedThreadPool.shutdown();之后的sysout输出。)包括main线程一共有6个线程。

main线程不执行run内代码段,直接往下继续执行其余代码。

main---------0 
pool-1-thread-2---------1
pool-1-thread-3---------2
pool-1-thread-4---------3

....

pool-1-thread-3---------497
pool-1-thread-2---------498
pool-1-thread-4---------499
pool-1-thread-5---------500

 

关于main线程:main线程可能在其余子线程执行完就执行到尾了。但是很多生产情况是要获取子线程结果来处理的。此时可以设置等待时间等待子线程结束

  1. // 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。

  2. threadPool.shutdown();

  3. 设置最长等待5秒

  4. if(!pool.awaitTermination(5, TimeUnit.SECONDS)){

  5. // 超时的时候向线程池中所有的线程发出中断(interrupted)。再超时直接强行关闭。

  6. pool.shutdownNow();

  7. }

 或者可以用join()方法,保证子线程执行完才执行主线程(这个例子用简单的new Thread,threadPool可以自己延伸):

  1. // 使用线程安全的Vector

  2. Vector threads = new Vector();

  3. for (int i = 0; i < 10; i++) {     .......  省略创建子线程方法

  4. threads.add(iThread);   // 将每一个子线程放到集合中,iThread代表某个子线程

  5. for (Thread iThread : threads) {     //在主线程中循环调用子线程的join()

  6. try {

  7. // 等待所有线程执行完毕

  8. iThread.join();

  9. } catch (InterruptedException e) {

  10. e.printStackTrace();

  11. }

  12. }

  13. System.out.println("主线执行。");  //这个sysout会在所有子线程完成后执行

 

关于shutdown:“问题解答完毕后请举手示意!”是shutdown方法。“老师我做完了!”是各个任务(Runnable)的运行结束。

shutdown只作为通知的作用

 

Vector和List :

....
//    final List list = new ArrayList();
      final Vector vec = new Vector();
....
//    synchronized (vec) {
          vec.add(j);
          System.out.println(Thread.currentThread().getName()+"---------"+vec.size());
          j--;
//    }
....

输出:

pool-1-thread-3---------3
pool-1-thread-1---------4
pool-1-thread-2---------3

....

pool-1-thread-1---------498
pool-1-thread-5---------499
pool-1-thread-4---------500

vector线程安全,list不安全。注调synchronized之后list添加元素个数少于500,vector安全添加500个元素。

但是由于add和sysout vector.size()没在一个锁里,所以,打印的元素个数是乱的 。

 

参考:https://blog.csdn.net/zaozi/article/details/38854561
https://blog.csdn.net/star890124/article/details/48243221

你可能感兴趣的:(ThreadPool线程池使用及解决主线程和子线程执行顺序问题)