Java多线程之线程创建和启动
来源:互联网 发布:cad数据连接管理器 编辑:程序博客网 时间:2024/04/25 23:41
Java使用Thread类表示线程,所有的线程对象必须是Thread类或其子类的实例,每个线程的作用,实际上就是执行一段程序刘,java使用线程执行体来代表着段程序流
创建线程3方法
继承Thread类
创建线程的方法1是继承Thread类,重写run()方法,该方法的方法体代表了线程需要完成的任务,因此run()方法叫做线程执行体
创建了Thread类子类的实例,即创建了线程对象
启动线程应该用线程对象的start()方法
public class FirstThread extends Thread { private int i; @override public void run(){ //继承Thread时,用this即可获取当前线程 for(;i < 100; i++){ System.out.println(this.getName() + " " + i); } }}public static void main(String[] args){ for(int i = 0; i < 100; i++){ //用Thread的静态方法获取当前主线程名称 System.out.println(Thread.currentThread().getName()); if(i == 20){ //除主线程,另外启动2个线程 new FirstThread().start(); new FirstThread().start(); } }}
实现Runnable接口
创建线程方法2,实现Runnable接口,重写run()方法
创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该对象才是真正的线程对象。通俗来说,就是用Thread来包装实现了Runnable接口的实例
调用start()方法,启动线程
SecondThread st = new SecondThread();new Thread(st).start();//也可以指定新线程的名称new Thread(st,"新线程1").start();//以上两条线程会共享st实例的变量
public class FirstThread implements Runnable { private int i; @override public void run(){ //实现Runnable接口,只能用Thread.currentThread()获取当前线程 for(;i < 100; i++){ System.out.println(Thread.currentThread().getName() + " " + i); } }}
使用Runnable接口创建的多线程可以共享线程类的实例变量。因为这种方式下,程序创建的Runnable对象只是线程的target,而多个线程可以共享一个target。
使用Callable和Future创建线程
JDK 1.5后,java.util.concurrent包下的Callable接口,它像是Runnable接口的增强版。Callable接口的call()方法可以作为线程的执行体,比run()方法强大。
那么,完全可以在Thread的target中传入一个Callable对象,执行体是call()方法。但问题在于:Callable不是Runnable的子接口,是JDK1.5新增接口,而且还有返回值
JDK 1.5提供了Future接口来代表Callable接口里call()方法的返回值,FutureTask是Future的实现类,并且实现了Runnable接口,那么可以作为Thread类的target
public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result 返回运行结果 * @throws Exception if unable to compute a result 若不能运算则抛出异常 */ V call() throws Exception;}
public interface Future<V> { //取消该Future关联的Callable任务 boolean cancel(boolean mayInterruptIfRunning); //如果Callable任务正常完成前被取消,返回true;完成后,不能取消 boolean isCancelled(); //如果Callable任务完成,返回true boolean isDone(); //返回Callable任务里call()方法的返回值。调用该方法将导致程序阻塞,须等到子线程结束才会得到返回值,也就是异步的 V get() throws InterruptedException, ExecutionException; //与上一样,不过可以设置最多阻塞timeout时间,时间单位为unit,若超时,抛异常 V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}
创建并启动有返回值的线程步骤:
创建Callable接口实现类,并实现call()方法
使用FutureTask类来包装Callable对象,FutureTask封装了Callable的call()方法返回值
创建Thread类的对象,传入FutureTask对象作为target,start()启动线程
使用FutureTask对象的get()方法获取线程返回值
public class ThirdThread { public static void main(String[] args) { ThirdThread rt = new ThirdThread(); //FutureTask包装Callable对象 FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() { @Override public Integer call() throws Exception { int i = 0; for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " 循环值" + i); } return i; } }); for(int i = 0; i < 100; i++){ //用Thread的静态方法获取当前主线程名称 System.out.println(Thread.currentThread().getName() + " 循环值" + i); if(i == 20){ //除主线程,另外启动1个线程 new Thread(task,"有返回值的线程").start(); try { System.out.println("子线程返回值 " + task.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } } }}
//结果部分有返回值的线程 循环值96有返回值的线程 循环值97有返回值的线程 循环值98有返回值的线程 循环值99子线程返回值 100main 循环值21main 循环值22main 循环值23main 循环值24
三种方式对比
继承Thread类,实现Runnable或Callable接口。实现接口实现多线程的方式大体相同
实现接口的优缺点:
Pros:
线程类实现了Runnable或Callable接口,可继承其他类
多个线程可以共享一个target对象(一个Runnable对象),所以适合多个相同线程处理同一个资源,从而将CPU,代码和数据分开,形成清晰的模型
Cons:
- 编程稍微复杂,若要访问当前线程,只能用Thread.currentThread()
继承Thread的优缺点:
Pros:
- 编写简单,this即可获得当前线程
Cons:
- 不能再继承其他类
综上,推荐使用Runnable或Callable接口
- Java多线程之线程创建和启动
- java多线程之创建和启动线程
- [疯狂Java]多线程:创建和启动线程
- Java多线程之创建任务和线程
- Java之线程的创建和启动
- Java基础-多线程-①线程的创建和启动
- Java基础-多线程-①线程的创建和启动
- Java基础-多线程-①线程的创建和启动
- 线程——Java之线程的创建和启动
- Java多线程之创建线程
- java并发多线程,线程的创建启动
- 多线程01--线程的创建和启动
- 创建和启动java线程
- Java线程创建和启动
- java线程创建和启动
- java 线程 启动 和 创建
- Java学习笔记之线程的创建和启动
- Java 之 线程的创建和启动(一)
- 接口设计小结
- CSS基础知识-四(边框样式、caption、表格居中、边框宽度和高度、id和class的区别、Div+CSS布局)
- 底层方法封装
- Middle-题目121:15. 3Sum
- SVM入门(五)线性分类器的求解——问题的描述Part2
- Java多线程之线程创建和启动
- BZOJ3416: Poi2013 Take-out
- SQL SERVER 索引碎片
- 分片报文
- CSS基础知识-五(CSS定位、左右布局方法)
- Android - 文件读写操作 总结
- 二分图匈牙利算法模板
- Hat's Fibonacci
- 在Excel中获得汉字的首字母