Java 线程对比(Thread,Runnable,Callable)实例详解
Java 线程对比Thread,Runnable,Callable java 使用 Thread 类代表线程,所有现场对象都必须是 Thread 类或者其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流。java 使用线程执行体来代表这段程序流。 1.继承Thread 类创建线程 启动多线程的步骤如下: (1)定义Thread 类的子类,并重写该类的run() 方法,该run() 方法的方法体就代表类线程需要完成的任务。因此把run() 方法称为线程执行体。 相关代码如下: /** * 继承 thread 的内部类,以买票例子 */ public class FirstThread extends Thread{ private int i; private int ticket = 10; @Override public void run() { for (;i<20;i++) { //当继承thread 时,直接使用this 可以获取当前的线程,getName() 获取当前线程的名字 // Log.d(TAG,getName()+" "+i); if(this.ticket>0){ Log.e(TAG,getName() + ",卖票:ticket=" + ticket--); } } } } private void starTicketThread(){ Log.d(TAG,"starTicketThread,"+Thread.currentThread().getName()); FirstThread thread1 = new FirstThread(); FirstThread thread2 = new FirstThread(); FirstThread thread3 = new FirstThread(); thread1.start(); thread2.start(); thread3.start(); //开启3个线程进行买票,每个线程都卖了10张,总共就30张票 } 运行结果:
2.实现 Runnable 接口创建线程 注意:public class Thread implements Runnable (1)定义 Runnable 接口的实现类,并重写该接口的run()方法,该run() 方法的方法体同样是该线程的线程执行体。 相关代码如下: /** * 实现 runnable 接口,创建线程类 */ public class SecondThread implements Runnable{ private int i; private int ticket = 100; @Override public void run() { for (;i<20;i++) { //如果线程类实现 runnable 接口 //获取当前的线程,只能用 Thread.currentThread() 获取当前的线程名 Log.d(TAG,Thread.currentThread().getName()+" "+i); if(this.ticket>0){ Log.e(TAG,Thread.currentThread().getName() + ",卖票:ticket=" + ticket--); } } } } private void starTicketThread2(){ Log.d(TAG,"starTicketThread2,"+Thread.currentThread().getName()); SecondThread secondThread = new SecondThread(); //通过new Thread(target,name)创建新的线程 new Thread(secondThread,"买票人1").start(); new Thread(secondThread,"买票人2").start(); new Thread(secondThread,"买票人3").start(); //虽然是开启了3个线程,但是一共只买了100张票 } 运行结果:
3.使用 Callable 和Future 创建线程 从 java 5 开始,Java 提供了 Callable 接口,该接口是runnable 的增强版,Callable 提供类一个 call() 方法可以作为线程执行体,但是call() 方法的功能更强大。 (1) call() 方法可以有返回值 因此我们完全可以提供一个callable 对象作为Thread的 target,而该线程的执行体就是该callable 对象的call() 方法。同时 java 5 提供了 Future 接口 来代表Callable 接口里 call() 方法的返回值,并且提供了一个 futureTask 的实现类,该实现类实现类 future 接口,并实现了runnable 接口―可以作为Thread 类的target. 启动步骤如下: (1)创建callable接口的实现类,并实现call() 方法,该call() 方法将作为线程的执行体,且该call() 方法是有返回值的。 相关代码如下: /** * 使用callable 来实现线程类 */ public class ThirdThread implements Callable<Integer>{ private int ticket = 20; @Override public Integer call(){ for ( int i = 0;i<10;i++) { //获取当前的线程,只能用 Thread.currentThread() 获取当前的线程名 // Log.d(TAG,卖票:ticket=" + ticket--); } } return ticket; } } private void starCallableThread(){ ThirdThread thirdThread = new ThirdThread(); FutureTask<Integer> task = new FutureTask<Integer>(thirdThread); new Thread(task,"有返回值的线程").start(); try { Integer integer = task.get(); Log.d(TAG,"starCallableThread,子线程的返回值="+integer); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } 运行结果:
4.三种方式的对比 采用继承Thread 类的方式创建多线程 劣势: 已经继承Thread类不能再继承其他父类。 优势: 编写简单 采用继承Runnable,Callable 接口的方式创建多线程 劣势: 编程稍微有点复杂,如果需要访问当前线程必须使用Thread.currentThread() 优势: (1)还可以继承其他类 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |