java多线程(二)

善于思考,拥抱变化,才能拥有未来

一、Threads 和 Runnables

 1   public void researchThread(){
 2         Runnable task = () -> {
 3             String threadName = Thread.currentThread().getName();
 4             System.out.println("Hello " + threadName);
 5         };
 6 
 7         task.run();
 8 
 9         Thread thread = new Thread(task);
10         thread.start();
11 
12         System.out.println("Done!");
13     }

  运行结果为:

  Hello main
  Done!
  Hello Thread-0

  或者:

  Hello main
  Hello Thread-0
  Done!

也可以在线程调用时,加入线程休眠来观察线程调用流程。
TimeUnit.SECONDS.sleep(1);

二、ExecutorService

1. newSingleThreadExecutor

1   public static void getExceterService1(){
2         ExecutorService executor = Executors.newSingleThreadExecutor();
3         executor.submit(() -> {
4             String threadName = Thread.currentThread().getName();
5             System.out.println("Hello " + threadName);
6         });
7     }

2. 关闭executors

  /**
     * shutdwon()会等待正在执行的任务执行完
     * shutdownNow()止所有正在执行的任务并立即关闭execuotr
     */
    public static void shutdownExcuterService2(){
        ExecutorService executor = Executors.newSingleThreadExecutor();
        try {
            System.out.println("attempt to shutdown executor");
            executor.shutdown();
            executor.awaitTermination(5, TimeUnit.SECONDS);
        }catch (InterruptedException e) {
            System.err.println("tasks interrupted");
        }finally {
            if (!executor.isTerminated()) {
                System.err.println("cancel non-finished tasks");
            }
            executor.shutdownNow();
            System.out.println("shutdown finished");
        }
    }

3.callable提交线程任务-newFixedThreadPool

  public static void testCallable1() throws ExecutionException, InterruptedException {
        Callable<Integer> task = () -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                return 123;
            }
            catch (InterruptedException e) {
                throw new IllegalStateException("task interrupted", e);
            }
        };

        ExecutorService executor = Executors.newFixedThreadPool(1);
        Future<Integer> future = executor.submit(task);

        System.out.println("future done? " + future.isDone());

        Integer result = future.get();

        System.out.println("future done? " + future.isDone());
        System.out.print("result: " + result);
    }

  执行结果为:

  future done? false
  future done? true
  result: 123

  注:关闭executor,所有的未中止的future都会抛出异常。

4. 任何future.get()调用都会阻塞,然后等待直到callable中止。在最糟糕的情况下,一个callable持续运行——因此可以简单的传入一个时长来避免这种情况。

 1   public void getTimeoutException() throws InterruptedException, ExecutionException, TimeoutException {
 2         ExecutorService executor = Executors.newFixedThreadPool(1);
 3 
 4         Future<Integer> future = executor.submit(() -> {
 5             try {
 6                 TimeUnit.SECONDS.sleep(2);
 7                 return 123;
 8             }
 9             catch (InterruptedException e) {
10                 throw new IllegalStateException("task interrupted", e);
11             }
12         });
13 
14         future.get(1, TimeUnit.SECONDS);
15     } 

  会抛出异常:

  java.util.concurrent.TimeoutException
  at java.util.concurrent.FutureTask.get(FutureTask.java:205)
  at com.example.junit.concurrent.LearnCallable.getTimeoutException(LearnCallable.java:51)
  at com.example.junit.concurrent.LearnCallable.main(LearnCallable.java:99)

5. invokeAll

 1   public void testInvokeAll() throws InterruptedException {
 2         ExecutorService executor = Executors.newWorkStealingPool();
 3 
 4         List<Callable<String>> callables = Arrays.asList(
 5                 () -> "task1",
 6                 () -> "task2",
 7                 () -> "task3");
 8 
 9         executor.invokeAll(callables)
10                 .stream()
11                 .map(future -> {
12                     try {
13                         return future.get();
14                     }
15                     catch (Exception e) {
16                         throw new IllegalStateException(e);
17                     }
18                 })
19                 .forEach(System.out::println);
20     }

6.invokeAny-在等待future对象的过程中,这个方法将会阻塞直到第一个callable中止然后返回这一个callable的结果。

 1   public void testInvokeAny() throws ExecutionException, InterruptedException {
 2 
 3         ExecutorService executor = Executors.newWorkStealingPool();
 4 
 5         List<Callable<String>> callables = Arrays.asList(
 6                 callable("task1", 2),
 7                 callable("task2", 1),
 8                 callable("task3", 3));
 9 
10         String result = executor.invokeAny(callables);
11         System.out.println(result);
12 
13     }
14 
15     private Callable<String> callable(String result, long sleepSeconds) {
16         return () -> {
17             TimeUnit.SECONDS.sleep(sleepSeconds);
18             return result;
19         };
20     }

7.ScheduledExecutorService支持任务调度,持续执行或者延迟一段时间后执行。

 1   public static void testScheduled() throws InterruptedException {
 2         ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
 3 
 4         Runnable task = () -> System.out.println("Scheduling: " + System.nanoTime());
 5         ScheduledFuture<?> future = executor.schedule(task, 3, TimeUnit.SECONDS);
 6 
 7         TimeUnit.MILLISECONDS.sleep(1337);
 8 
 9         long remainingDelay = future.getDelay(TimeUnit.MILLISECONDS);
10         System.out.printf("Remaining Delay: %sms", remainingDelay);
11     }
executor.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.SECONDS);
scheduleAtFixedRate()并不考虑任务的实际用时。所以,如果你指定了一个period为1分钟而任务需要执行2分钟,那么线程池为了性能会更快的执行。
executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS);
scheduleWithFixedDelay()在你不能预测调度任务的执行时长时是很有用的。
posted @ 2018-12-16 23:33  在旅途上追忆寻梦  阅读(145)  评论(0编辑  收藏  举报