JAVA多线程
来源:互联网 发布:2018网络教育报名时间 编辑:程序博客网 时间:2024/06/07 05:21
一:JAVA实现多线程方式有三种。
1:实现runable接口。
2:类继承Tread类,实质Thread也是实现了runable接口。
3:使用ExecutorService。
1:继承Thread类:
package com.ida.console.web.controller.usercert;public class ThreadTest extends Thread { private String name; public ThreadTest(String name) { this.name = name; } @Override public void run() { System.out.println(Thread.currentThread().getName())//当前线程 System.out.println(name); } public static void main(String[] args) { ThreadTest thread1 = new ThreadTest("1"); ThreadTest thread2 = new ThreadTest("2"); ThreadTest thread3 = new ThreadTest("3"); thread1.start(); thread2.start(); thread3.start(); }}
上面的代码启动了三个线程,运行结果 123、231等没有顺序。
2:实现runable接口
package com.ida.console.web.controller.usercert;public class RunableTest implements Runnable { private String name; public RunableTest(String name) { this.name = name; } @Override public void run() { System.out.println(Thread.currentThread().getName())//当前线程 System.out.println(name); } public static void main(String[] args) { Thread thread1 = new Thread(new RunableTest("1")); Thread thread2 = new Thread(new RunableTest("2")); Thread thread3 = new Thread(new RunableTest("3")); thread1.start(); thread2.start(); thread3.start(); }}
上面的代码启动了三个线程,运行结果 123、231等没有顺序。
继承Thread和实现runable都能实现多线程:
比较下面两个例子
1:
package com.ida.console.web.controller.usercert;public class ThreadTest extends Thread { private int a = 1000; @Override public void run() { while (a > 0) { System.out.println(Thread.currentThread().getName())//当前线程 System.out.println(a--); } } public static void main(String[] args) { ThreadTest thread1 = new ThreadTest(); ThreadTest thread2 = new ThreadTest(); ThreadTest thread3 = new ThreadTest(); thread1.start(); thread2.start(); thread3.start(); }}
2:
package com.ida.console.web.controller.usercert;public class RunableTest implements Runnable { private int a = 1000; @Override public void run() { while (a > 0) { System.out.println(Thread.currentThread().getName())//当前线程 System.out.println(a--); } } public static void main(String[] args) { RunableTest runableTest = new RunableTest(); Thread thread1 = new Thread(runableTest); Thread thread2 = new Thread(runableTest); Thread thread3 = new Thread(runableTest); thread1.start(); thread2.start(); thread3.start(); 或者 for(int i=0;i<3;i++){ Thread thread = new Thread(runableTest); thread.start(); } }}
两个都是启动三个线程,但是第一个会执行打印出3000条数据,也就是每个线程都会执行一遍run,第二个只会打印出1000条数据,因为第一个实例化了三个对象,第二个实例化一个对象,启动三个线程共享run方法。如果是一个买票系统,就必须使用第二种。本来只有1000张票,第一种卖出了3000张,是错误的。合理选择应用。所以程序开发中只要是多线程肯定永远以实现Runnable接口为主:
- 避免点继承的局限,一个类可以继承多个接口。
- 适合于资源的共享
3:ExecutorService实现
ExecutorService是一种异步执行的多线程,可以让线程在后台执行,实现ExecutorService 就是创建线程池。主要有三种方式:
1:newCachedThreadPool,缓存型线程池,使用时首先查询缓存池有没有建立空闲的线程,有的话就使用,没有就新建一个并加入到线程池,没考虑到服务器的压力。用于执行异步周期很短的任务。线程池中的线程如果没有使用会在60S后移除线程池。不用担心线程不会结束。
2:newFixedThreadPool是创建一个固定线程数量的线程池,每一个任务都会创建一个线程,直到达到固定的数量,后面的任务等待线程池中的线程任务处理完后,又补充一个新任务线程进来。
3:newSingleThreadExecutor创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
4:newScheduledThreadPool创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。(没有使用过)
使用方法:
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
ExecutorService executorService2 = Executors.newFixedThreadPool(10);
ExecutorService executorService3 = Executors.newScheduledThreadPool();
ExecutorService executorService4 = Executors.newCachedThreadPool();
将任务委托给ExecutorService有几种不同的方式。
1:execute(Runnable)
ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(new Runnable() { public void run() { System.out.println("。。。"); } }); executorService.shutdown();
这种方式是没有返回值的。
2:submit(Runnable)
Future future = executorService.submit(new Runnable() { public void run() { System.out.println("Asynchronous task"); } }); //如果任务结束执行则返回 null System.out.println("future.get()=" + future.get());
这种方式会返回一直future对象,可以判断任务是否结束,如果任务结束则返回 null
3:submit(Callable)
List<Future<String>> resultList = new ArrayList<Future<String>>(); Future future = executorService.submit(new Callable(){ public Object call() throws Exception { System.out.println("Asynchronous Callable"); return "Callable Result"; } }); resultList.add(future);for (Future<String> fs : resultList){ try{ while(!fs.isDone);//Future返回如果没有完成,则一直循环等待,直到Future返回完成 System.out.println(fs.get()); //打印各个线程(任务)执行的结果 }catch(InterruptedException e){ e.printStackTrace(); }catch(ExecutionException e){ e.printStackTrace(); }finally{ //启动一次顺序关闭,执行以前提交的任务,但不接受新任务 executorService.shutdown(); } }
这种方式可以获取返回的结果。
4:invokeAny(…)
ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<Callable<String>> callables = new HashSet<Callable<String>>(); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 1"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 2"; } }); callables.add(new Callable<String>() { public String call() throws Exception { return "Task 3"; } }); String result = executorService.invokeAny(callables); System.out.println("result = " + result); executorService.shutdown();
方法 invokeAny() 接收壹個包含 Callable 对象的集合作为参数。调用该方法不会返回 Future 对象,而是返回集合中某壹個 Callable 对象的结果,而且无法保证调用之后返回的结果是哪壹個 Callable,只知道它是这些 Callable 中壹個执行结束的 Callable 对象。
5:invokeAll(…)
package com.ida.console.web.controller.usercert;import java.util.HashSet;import java.util.List;import java.util.Set;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class Test6 { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<Callable<String>> callables = new HashSet<Callable<String>>(); callables.add(new Callable<String>() { public String call() throws Exception { System.out.println(Thread.currentThread().getName()); return "Task 1"; } }); callables.add(new Callable<String>() { public String call() throws Exception { System.out.println(Thread.currentThread().getName()); return "Task 2"; } }); callables.add(new Callable<String>() { public String call() throws Exception { System.out.println(Thread.currentThread().getName()); return "Task 3"; } }); List<Future<String>> result = null; try { result = executorService.invokeAll(callables); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for (Future<String> future : result) { try { System.out.println(future.get()); } catch (InterruptedException | ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } executorService.shutdown(); }}
方法 invokeAll() 会调用存在于参数集合中的所有 Callable 对象,并且返回壹個包含 Future 对象的集合,你可以通过这個返回的集合来管理每個 Callable 的执行结果。
需要注意的是,任务有可能因为异常而导致运行结束,所以它可能并不是真的成功运行了。但是我们没有办法通过 Future 对象来了解到这個差异。
Executors关闭:
当使用 ExecutorService 完毕之后,我们应该关闭它,这样才能保证线程不会继续保持运行状态。
举例来说,如果你的程序通过 main() 方法启动,并且主线程退出了你的程序,如果你还有一个活动的 ExecutorService 存在于你的程序中,那么程序将会继续保持运行状态。存在于 ExecutorService 中的活动线程会阻止Java虚拟机关闭。
为了关闭在 ExecutorService 中的线程,你需要调用 shutdown() 方法。ExecutorService 并不会马上关闭,而是不再接收新的任务,一但所有的线程结束执行当前任务,ExecutorServie 才会真的关闭。所有在调用 shutdown() 方法之前提交到 ExecutorService 的任务都会执行。
如果你希望立即关闭 ExecutorService,你可以调用 shutdownNow() 方法。这各方法会尝试马上关闭所有正在执行的任务,并且跳过所有已经提交但是还没有运行的任务。
- 【Java多线程】多线程死锁
- Java 多线程
- java 多线程
- java多线程
- JAVA多线程
- java多线程
- JAVA多线程
- java多线程
- JAVA 多线程
- Java多线程
- java多线程
- JAVA 多线程
- Java 多线程
- Java 多线程
- java多线程
- Java 多线程
- Java多线程
- java 多线程
- 百度地图不显示地址—只有网格
- git 删除github上的文件
- [LeetCode]Add Digits
- 初学风水-某商务中心店铺
- go实现一个简单的游戏服务器框架(lotou)基本设计
- JAVA多线程
- Android N 高通平台飞行模式下拨打紧急拨号112流程
- 十年Hello World,写的是人生
- Android高级控件(一)——ListView绑定CheckBox实现全选,增加和删除等功能
- 英文经典好歌《Nothing's Gonna Change My Love For You》没有什么能够改变我对你的爱-英译中
- ubuntu下qt插件qwt的使用
- Mysql用事件和存储过程每月创建一张数据库表
- Ubuntu Erroe found when loading /root/.profile解决方案
- linux安装maven