初学Java多线程,后续继续改进
一,Callable
Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务
Callable和Runnable的区别如下:
1.Callable定义的方法是call,而Runnable定义的方法是run。
2.Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。
3.Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。
二,Executor
A,几种不同的ExecutorService线程池对象:
1. newCachedThreadPool() 缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse.如果没有,就建一个新的线程加入池中,自增型
2. newFixedThreadPool(int var0)任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子
3.SingleThreadExecutor()单例线程,任意时间池中只能有一个线程
4.ScheduledThreadPool()这个池子里的线程可以按schedule依次delay执行,或周期执行
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(2); System.out.println("开始时间"+new Date()); threadPool.schedule(new MyExecutor(),2,TimeUnit.SECONDS); threadPool.schedule(new MyExecutor(),4,TimeUnit.SECONDS);
B,ExecutorService接口常用方法:
1.void shutdown()
这个方法会平滑地关闭ExecutorService,当我们调用这个方法时,ExecutorService停止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另一类是还没有开始执行的),当所有已经提交的任务执行完毕后将会关闭ExecutorService
ExecutorService service = Executors.newCachedThreadPool(); service.submit(new MyExecutor()); service.shutdown();
2.boolean isTerminated(int timeout,TimeUnit unit)/boolean isShutdown()
这个方法有两个参数,一个是timeout即超时时间,另一个是unit即时间单位。这个方法会使线程等待timeout时长,当超过timeout时间后,会监测ExecutorService是否已经关闭,若关闭则返回true,否则返回false。一般情况下会和shutdown方法组合使用
ExecutorService executorService= Executors.newCachedThreadPool(); executorService.submit(new MyExecutor()); executorService.submit(new MyExecutor()); executorService.submit(new MyExecutor()); executorService.submit(new MyExecutor()); executorService.shutdown(); System.out.println(executorService.isTerminated()+”-----"+executorService.isShutdown());
3.List<Runnable> shutdownNow()
个方法会强制关闭ExecutorService,它将取消所有运行中的任务和在工作队列中等待的任务,这个方法返回一个List列表,列表中返回的是等待在工作队列中的任务
ExecutorService service = Executors.newFixedThreadPool(3); service.submit(new MyExecutor()); service.submit(new MyExecutor()); service.submit(new MyExecutor()); service.submit(new MyExecutor()); List<Runnable> runnables = service.shutdownNow(); System.out.println("等待个数:"+runnables.size());
4.boolean awaitTermination(long timeout, TimeUnit unit)
这个方法有两个参数,一个是timeout即超时时间,另一个是unit即时间单位。这个方法会使线程等待timeout时长,当超过timeout时间后,会监测ExecutorService是否已经关闭,若关闭则返回true,否则返回false。一般情况下会和shutdown方法组合使用
ExecutorService service = Executors.newCachedThreadPool(); service.submit(new MyExecutor()); service.submit(new MyExecutor()); service.submit(new MyExecutor()); service.submit(new MyExecutor()); service.shutdown(); try { while (!service.awaitTermination(1, TimeUnit.SECONDS)) { System.out.println(“线程池没有关闭”); } System.out.println(“线程池已经关闭");
三,Future
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。FutureTask类是Future 的一个实现,并实现了Runnable,所以可通过Excutor(线程池) 来执行,也可传递给Thread对象执行,一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果
常用方法:
1.boolean cancel(boolean mayInterruptIfRunning) 试图取消对此任务的执行。如果任务已完成、或已取消,或者由于某些其他原因而无法取消,则此尝试将失败。当调用 cancel 时,如果调用成功,而此任务尚未启动,则此任务将永不运行。如果任务已经启动,则 mayInterruptIfRunning 参数确定是否应该以试图停止任务的方式来中断执行此任务的线程。此方法返回后,对 isDone() 的后续调用将始终返回 true。如果此方法返回 true,则对 isCancelled() 的后续调用将始终返回 true
2.boolean isCancelled():如果在任务正常完成前将其取消,则返回 true,如果cancel方法返回 true,则对 isCancelled() 的后续调用将始终返回 true
3.boolean isDone():如果任务已完成,则返回 true。 可能由于正常终止、异常或取消而完成,在所有这些情况中,此方法都将返回 true。
4.V get()throws InterruptedException,ExecutionException:如有必要,等待计算完成,然后获取其结果。
5.V get(long timeout,TimeUnit unit) throws InterruptedException,ExecutionException,TimeoutException:如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)
class PGPageModelWorker implements Callable<Integer> { private int shopId; public PGPageModelWorker(int shopId) { this.shopId = shopId; } @Override public Integer call() throws Exception { Random rand = new Random(); int sleep=rand.nextInt(2000) + 500; // Thread.sleep(sleep); int s = shopId + 1; System.out.println(shopId+"执行时间---" + sleep+"毫秒"); return s; } }
class FutureTask2Test{ public static void main(String[] args) throws InterruptedException { final ConcurrentHashMap<String, Integer> modelMap = new ConcurrentHashMap<String, Integer>(); final List<Integer> data=Collections.synchronizedList(new ArrayList<Integer>()); ExecutorService executor = Executors.newCachedThreadPool(); final CountDownLatch countDownLatch = new CountDownLatch(10);// Long startdate=System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { final int id = i; executor.submit(new FutureTask<Integer>(new PGPageModelWorker(id)) { @Override protected void done() { try { modelMap.put("key" + id, get()); data.add(get()); } catch (Exception e) { modelMap.put("key" + id, 0); } finally { countDownLatch.countDown(); } } }); } System.out.println("----做其他的事------"); System.out.println("------做其他的事----"); System.out.println("-----做其他的事-----"); try { Thread.sleep(3000); System.out.println("睡三秒"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("-----做其他的事-----"); System.out.println("-----做其他的事-----"); System.out.println("-----做其他的事-----"); System.out.println("-----做其他的事-----"); int timeout = 3000; countDownLatch.await(timeout, TimeUnit.MILLISECONDS);// 超时时间 Long enddate=System.currentTimeMillis(); System.out.println("执行时间:"+(enddate-startdate)); Iterator<String> iterator=modelMap.keySet().iterator(); while (iterator.hasNext()){ String key=iterator.next(); System.out.println(key+"-----"+modelMap.get(key)); } System.out.println("---list遍历--------"); Long start1=System.currentTimeMillis(); for(Integer d:data){ System.out.println(d); } System.out.println("遍历时间:"+(System.currentTimeMillis()-start1)); System.out.println("list.size:"+data.size()); } }
CountDownLatch
它可以让某些任务完成以后再继续运行下面的内容,每个任务本身执行完毕后让计数器减一,直到计数器清零后,以下的内容才可以继续运行,否则将阻塞等待
CountDownLatch有以下基本方法:
1)await(),阻塞等待,直到计数器清零
2)await(int timeout, TimeUnit unit),使线程阻塞,除非被中断或者超过等待的最大时间
如果达到计数器清零,则await返回true,如果等待超过了最大的等待时间,则返回false
3)countDown(),计数器减一,当计数器清零时,await的线程被唤醒,线程继续执行
4)getCount (),获取当前计数器的大小
public static void main(String[] args) throws Exception{ final CountDownLatch cdOrder=new CountDownLatch(1); final CountDownLatch cdAnswer=new CountDownLatch(3); System.out.println("等待运动员入场---------------"); try { ExecutorService executor= Executors.newCachedThreadPool();; for (int i = 1; i < 4; i++) { final int c=i; executor.submit(new Runnable() { @Override public void run() { try { System.out.println("运动员"+c+"准备就绪"); cdOrder.await(); System.out.println("运动员"+c+"已经起跑"); Random rand = new Random(); Thread.sleep(rand.nextInt(2000) + 500); cdAnswer.countDown(); System.out.println("运动员"+c+"已到终点"); System.out.println("还剩"+cdAnswer.getCount()+"个运动员未到"); } catch (Exception e) { System.out.println("runable problem i="+c); e.printStackTrace(); } } }); } } catch (Exception e) { System.out.println("thread problem"); e.printStackTrace(); } try { Thread.sleep(1000); System.out.println("裁判已发布号令-----------------"); cdOrder.countDown(); cdAnswer.await(); System.out.println("裁判宣布结果------------"); } catch (Exception e){ System.out.println("main problem"); e.printStackTrace(); } }
五,CompletionService
将生产新的异步任务与使用已完成任务的结果分离开来的服务,生产者 submit 执行的任务。使用者 take 已完成的任务,并按照完成这些任务的顺序处理它们的结果
CompletionService有以下基本方法:
Future<V> submit(Callable<V> task);
Future<V> submit(Runnable task, V result);
Future<V> take() throws InterruptedException;
Future<V> poll();
Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;
class completionService2{ public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); CompletionService<Integer> completionServcie = new ExecutorCompletionService<Integer>( executor); completionServcie.submit(new Runnable() { @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } },1); try { System.out.println(completionServcie.poll(2000, TimeUnit.MILLISECONDS).get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/weizunde/article/details/48056321