zoukankan      html  css  js  c++  java
  • Java并发编程核心方法与框架-ExecutorService的使用

    在ThreadPoolExecutor中使用ExecutorService中的方法

    方法invokeAny()和invokeAll()具有阻塞特性

    方法invokeAny()取得第一个完成任务的结果值,当第一次任务执行完成后,会调用interrupt()方法将其他任务中断,所以在这些任务中可以结合if(Thread.currentThread().isInterrupted() == true)来决定任务是否继续运行。

    1. 无if(Thread.currentThread().isInterrupted() == true)代码:已经获得第一个运行的结果值后,其他线程继续运行。
    2. 有if(Thread.currentThread().isInterrupted() == true)代码:已经获得第一个运行的结果值后,其他线程如果使用throw new InterruptedExeception()代码则这些线程中断,虽然throw抛出了异常,但在main线程中并不能捕获异常。如果要捕获异常,则需要在Callable中使用try-catch进行捕获。

    方法invokeAll()等全部线程任务执行完毕后,取得全部完成任务的结果值。

    public class MyCallableA implements Callable<string> {
    
    	@Override
    	public String call() throws Exception {
    		System.out.println("MyCallableA.call() begin " + System.currentTimeMillis());
    		for (int i = 0; i &lt; 123456; i++) {
    			Math.random();
    			Math.random();
    			Math.random();
    			System.out.println("MyCallableA.call() " + i);
    		}
    		System.out.println("MyCallableA.call() end " + System.currentTimeMillis());
    		return "MyCallableA_return";
    	}
    }
    
    public class MyCallableB1 implements Callable<string> {
    
    	@Override
    	public String call() throws Exception {
    		System.out.println("MyCallableB1.call() begin " + System.currentTimeMillis());
    		for (int i = 0; i &lt; 223456; i++) {
    			Math.random();
    			Math.random();
    			Math.random();
    			System.out.println("MyCallableB1.call() " + i);
    		}
    		System.out.println("MyCallableB1.call() end " + System.currentTimeMillis());
    		return "MyCallableB1_return";
    	}
    }
    
    public class MyCallableB2 implements Callable<string> {
    
    	@Override
    	public String call() throws Exception {
    		System.out.println("MyCallableB2.call() begin " + System.currentTimeMillis());
    		for (int i = 0; i &lt; 223456; i++) {
    			if (!Thread.interrupted()) {
    				Math.random();
    				Math.random();
    				Math.random();
    				System.out.println("MyCallableB2.call() " + i);
    			} else {
    				System.out.println("MyCallableB2.call() 抛出异常中断了");
    				throw new InterruptedException();
    			}
    		}
    		System.out.println("MyCallableB2.call() end " + System.currentTimeMillis());
    		return "MyCallableB2_return";
    	}
    }
    
    public class Run1 {
    	public static void main(String[] args) {
    		try {
    			List list = new ArrayList&lt;&gt;();
    			list.add(new MyCallableA());
    			list.add(new MyCallableB1());
    			ExecutorService executorService = Executors.newCachedThreadPool();
    			String getValueA = executorService.invokeAny(list);
    			System.out.println("Run1.main() getValueA=" + getValueA);
    			System.out.println("Run1.main() end");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    运行结果如下:

    MyCallableA.call() 98
    MyCallableA.call() 99
    MyCallableA.call() end 1472041166456
    Run1.main() getValueA=MyCallableA_return
    Run1.main() end
    MyCallableB1.call() 60
    MyCallableB1.call() 61
    MyCallableB1.call() 62
    

    虽然方法invokeAny()已经取得returnA的值,但线程B还在继续运行中,直到运行完毕。

    使用MyCallable2类

    public class MyCallableB2 implements Callable<string> {
    
    	@Override
    	public String call() throws Exception {
    		System.out.println("MyCallableB2.call() begin " + System.currentTimeMillis());
    		for (int i = 0; i &lt; 500; i++) {
    			if (!Thread.interrupted()) {
    				Math.random();
    				Math.random();
    				Math.random();
    				System.out.println("MyCallableB2.call() " + i);
    			} else {
    				System.out.println("MyCallableB2.call() 抛出异常中断了");
    				throw new InterruptedException();
    			}
    		}
    		System.out.println("MyCallableB2.call() end " + System.currentTimeMillis());
    		return "MyCallableB2_return";
    	}
    }
    
    public class Run2 {
    	public static void main(String[] args) {
    		try {
    			List list = new ArrayList&lt;&gt;();
    			list.add(new MyCallableA());
    			list.add(new MyCallableB2());
    			ExecutorService executorService = Executors.newCachedThreadPool();
    			String getValueA = executorService.invokeAny(list);
    			System.out.println("Run1.main() getValueA=" + getValueA);
    			System.out.println("Run1.main() end");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    此时控制台输出结果如下:

    ......
    MyCallableA.call() 95
    MyCallableA.call() 96
    MyCallableA.call() 97
    MyCallableA.call() 98
    MyCallableA.call() 99
    MyCallableA.call() end 1472041795166
    Run1.main() getValueA=MyCallableA_return
    Run1.main() end
    MyCallableB2.call() 抛出异常中断了
    

    线程A执行完毕后,线程池将线程B设置为中断interrupted状态,而线程B可以自定义对中断interruptted状态进行处理,可以使用Thread.interrupted()结合throw new InterruptedException()进行处理。


    方法invokeAny()与执行慢的任务异常

    快的任务优先执行完毕之后,执行慢的任务出现异常时,默认情况下不会在控制台输出异常信息。可以使用try-catch捕获异常。

    ....//代码见P212

    也可以在Callable中使用try-catch捕获异常信息,此时不能在main线程中捕获到异常。

    ....//代码见P214


    方法invokeAny()与执行快的任务异常

    执行快的任务出现异常时,默认情况下是不在控制台输出异常信息的。除非显式使用try-catch捕获,而等待执行慢的任务返回结果值。
    ....//代码见P217

  • 相关阅读:
    iSCSI又称为IPSAN
    文档类型定义DTD
    HDU 2971 Tower
    HDU 1588 Gauss Fibonacci
    URAL 1005 Stone Pile
    URAL 1003 Parity
    URAL 1002 Phone Numbers
    URAL 1007 Code Words
    HDU 3306 Another kind of Fibonacci
    FZU 1683 纪念SlingShot
  • 原文地址:https://www.cnblogs.com/umgsai/p/5671664.html
Copyright © 2011-2022 走看看