java多线程编程--如何开始一个线程
2015-08-28 10:29
246 查看
近期下定决心开始学习java网络编程,目标是实现一个简单但稳定的聊天工具。由于自己一直从事服务器端开发工作,所以并不打算纠结于界面,so, 客户端也就用控制台作为输入输出了。结果在实践客户端的过程中,被多线程来了个当头棒喝!也是,本来网络编程就离不开多线程,既然问题出现了,那就解决吧!先从“开始一个线程”开始吧!
另外,查看Thread类会发现,Thread类并直接支持Callable,因而Callable要配合其他类才能好好工作。
支持Callable的途径有好几种,这里只写一种自己试验过的,其他的等以后再补充。
(1)配合FutureTask
FutureTask<V>实现了Runnable接口和Future接口(Futur可以获取异步线程执行的返回值),因此可以利用FutureTask来实现开始线程并获取线程执行结果。
示例如下:
输出结果:
可以看出,在要使用子线程的执行结果之前,我们可以坐一些其他事情,等需要用的时候,调用Future的get()方法就可以获取子线程的执行结果。
注意,Future的get()方法会一直阻塞到子线程执行结束。当然,我们可以使用get(long timeout, TimeUnit unit)函数来指定等待时间。
(2)TODO 配合ExecutorService
通过ExecutorService的submit方法可以执行Callable,对于线程池这一块暂时还没多少了解,后续自己实践之后再补充^ ^。
对于上述几种方式的选择,其实按需要来就行:
extends Thread的优点是你可以直接使用父类Thread给你提供的线程操作的方法,而缺点是java的类不支持多继承,因此使用起来可能没那么自由。
implements Runnable的优点是你可以实现其他多个接口,也可以继承其他类,自由度大大提高,而缺点则是对于线程的操作,要费一点心思^ ^。相对于继承Thread类,推荐使用实现Runnable的方式,这样程序扩展性更高。
implements Callable的优点是可以返回线程执行结果,抛出异常,对于要使用其他线程的执行结果的场景来说非常有用。
从入大学到工作,学习和接触的东西比较杂,C、C++,大学时代的主要编程语言课程,看过不少C和C++的书籍,实习期间Unix编程、MFC、Socket编程,对其了解算是比较深,但是却没有真正用他们开发过大的项目,一直不敢厚着脸皮说“对其了解算是比较深”。
毕业后进了一家电子商务公司,做web服务器开发去了...因此,又学会了struts MVC等框架的使用,js, html, jsp, Hbase、网络爬虫等等。但仅限于使用,没有深入地研究。而这一份工作的选择,也使java成为我工作的第一门语言。
一年后又进入一家游戏公司,从事游戏服务器开发工作。公司规模不大,但利润多多,自己被变身为多面手,游戏服务器、第三方支付、优惠活动、道具系统...甚至于web页面,哪里需要补哪里。期间又学会了Clojure语言及其相关技术...
仔细想想,工作中参与网络通讯、游戏基础架构等底层框架开发的机会真的很少(公司的大牛们早就已经开发好了,我们直接拿来使用),多的还是在其基础上编写一些游戏逻辑,java的高级特性也很少有用武之处。成长的速度满足不了内心的期望,这让我深感不安。“我是一名资深的游戏服务器端开发工程师”这句话还只是一颗种子,深埋土壤。现在只有不停的给它施肥,催它发芽、成长,也许过程会很缓慢,但还好,我已种下一颗种子。
1. java多线程的实现方式
1.1 继承Thread类
定义类如下:public SubThread extends Thread { @override public void run() { ... } }使用时:
Thread subThread = new SubThread(); subThread.start();可以使用Thread类已有的函数进行操作。
1.2 实现Runnable接口
定义类如下:public SubThread implements Runnable { public void run() { // doSomething... } }使用时:
SubThread subThread = new SubThread(); Thread thread = new Thread(subThread); thread.start();使用该方式实现的类其实是一个普通类,只是它实现了线程的run方法,因而将其注册到Thread类的对象中才能作为一个线程运行。
1.3 实现Callable接口
类定义如下:public SubThread implements Callable<String> { public String call() { // do something... } }可以看出,通过这种方式实现的线程带有返回值,Callable<String>指定返回值类型,并且Callable可以抛出异常,而Runnable则不能。
另外,查看Thread类会发现,Thread类并直接支持Callable,因而Callable要配合其他类才能好好工作。
支持Callable的途径有好几种,这里只写一种自己试验过的,其他的等以后再补充。
(1)配合FutureTask
FutureTask<V>实现了Runnable接口和Future接口(Futur可以获取异步线程执行的返回值),因此可以利用FutureTask来实现开始线程并获取线程执行结果。
示例如下:
public class TestCallable implements Callable<String> { public String call() throws InterruptedException { Thread.sleep(5000); return "call return"; } public static void main(String[] args) { TestCallable test = new TestCallable(); FutureTask<String> futrue = new FutureTask<String>(test); Thread thread = new Thread(futrue); thread.start(); // 在需要结果之前,可以坐其他事 System.out.println("hello"); try { System.out.println(futrue.get()); } catch (ExecutionException e) { System.out.println("执行callable时出错"); } catch (InterruptedException e) { System.out.println("执行callable时出错"); } System.out.println("结束语"); } }
输出结果:
hello call return 结束语
可以看出,在要使用子线程的执行结果之前,我们可以坐一些其他事情,等需要用的时候,调用Future的get()方法就可以获取子线程的执行结果。
注意,Future的get()方法会一直阻塞到子线程执行结束。当然,我们可以使用get(long timeout, TimeUnit unit)函数来指定等待时间。
(2)TODO 配合ExecutorService
通过ExecutorService的submit方法可以执行Callable,对于线程池这一块暂时还没多少了解,后续自己实践之后再补充^ ^。
2. 总结
起始研究Thread类就能发现,extends Thread 和 implements Runable是实现一个线程的最基本的方式,FutureTask这些都是在Runnable这块基石上实现的,Callable则必须依赖其他支持它的类才能执行,不然它和线程是没有半毛钱关系的。打好底层基础对于理解一些高层的用法非常有帮助,不然只是知其然不知其所以然。就像你如果不知道TCP协议,在用java网络编程时,对于出现的一些奇怪的现象,你就不知道是底层协议的原因,还是java自身的原因一样...扯远了~~对于上述几种方式的选择,其实按需要来就行:
extends Thread的优点是你可以直接使用父类Thread给你提供的线程操作的方法,而缺点是java的类不支持多继承,因此使用起来可能没那么自由。
implements Runnable的优点是你可以实现其他多个接口,也可以继承其他类,自由度大大提高,而缺点则是对于线程的操作,要费一点心思^ ^。相对于继承Thread类,推荐使用实现Runnable的方式,这样程序扩展性更高。
implements Callable的优点是可以返回线程执行结果,抛出异常,对于要使用其他线程的执行结果的场景来说非常有用。
3. 碎碎念
虽然自己这两年一直从事服务器端开发工作,但是对于java网络编程和多线程编程并没有深入了解。从入大学到工作,学习和接触的东西比较杂,C、C++,大学时代的主要编程语言课程,看过不少C和C++的书籍,实习期间Unix编程、MFC、Socket编程,对其了解算是比较深,但是却没有真正用他们开发过大的项目,一直不敢厚着脸皮说“对其了解算是比较深”。
毕业后进了一家电子商务公司,做web服务器开发去了...因此,又学会了struts MVC等框架的使用,js, html, jsp, Hbase、网络爬虫等等。但仅限于使用,没有深入地研究。而这一份工作的选择,也使java成为我工作的第一门语言。
一年后又进入一家游戏公司,从事游戏服务器开发工作。公司规模不大,但利润多多,自己被变身为多面手,游戏服务器、第三方支付、优惠活动、道具系统...甚至于web页面,哪里需要补哪里。期间又学会了Clojure语言及其相关技术...
仔细想想,工作中参与网络通讯、游戏基础架构等底层框架开发的机会真的很少(公司的大牛们早就已经开发好了,我们直接拿来使用),多的还是在其基础上编写一些游戏逻辑,java的高级特性也很少有用武之处。成长的速度满足不了内心的期望,这让我深感不安。“我是一名资深的游戏服务器端开发工程师”这句话还只是一颗种子,深埋土壤。现在只有不停的给它施肥,催它发芽、成长,也许过程会很缓慢,但还好,我已种下一颗种子。
相关文章推荐
- 通过代码快速理解Java代码块
- springMVC文件上传
- spring mvc
- Spring MVC入门案例(1)
- java dao通用方法
- eclipse集成git插件与本地使用
- Java笔记学习总结(三)
- 关于Java的一道内存的题目
- java在acm中的使用
- Java高手需要注意的25个学习目标
- Struts DispatchAction Example
- 基于 Annotation 拦截的 Spring AOP 权限验证方法
- 【Git】Git学习手册
- SpringMVC详细示例实战教程
- Struts ForwardAction Example
- Java web 开发环境搭建
- 关于Alipay支付宝接口(Java版)
- Java Web中的Action、Dao、Service、Model学习笔记-----阿冬专栏
- J2EE-BaseEntity.java
- java死锁检测