学习自:
有三种使用线程的方法:
- 实现 Runnable 接口;
- 实现 Callable 接口;
- 继承 Thread 类。
实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以理解为任务是通过线程驱动从而执行的。
实现Runnable接口
需要实现接口中的 run() 方法。
使用 Runnable 实例再创建一个 Thread 实例,然后调用 Thread 实例的 start() 方法来启动线程。
package JavaThread.Create; public class CreateByRunnable implements Runnable{ @Override public void run() { for (int i = 0; i<50; i++){ System.out.println(Thread.currentThread().getName()+" "+i); } } public static void main(String[] args) { CreateByRunnable createByRunnable = new CreateByRunnable(); Thread t1 = new Thread(createByRunnable, "线程1"); Thread t2 = new Thread(createByRunnable, "线程2"); t1.start(); t2.start(); } }
实现Callable接口
与 Runnable 相比,Callable 可以有返回值,返回值通过 FutureTask 进行封装。
package JavaThread.Create; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CreateByCallable implements Callable { @Override public Integer call() throws Exception { int i=0; for(;i<10;i++){ System.out.println(Thread.currentThread().getName() + "的循环变量i的值 :" + i); } return i; } public static void main(String[] args) throws ExecutionException, InterruptedException { CreateByCallable mc = new CreateByCallable(); FutureTask<Integer> ft = new FutureTask<>(mc); for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" 的循环变量i :" + i); if(i==20){ new Thread(ft,"有返回值的线程").start(); } } try{ System.out.println("子线程返回值 : " + ft.get()); }catch (Exception e){ e.printStackTrace(); } } }
继承Thread类
同样也是需要实现 run() 方法,因为 Thread 类也实现了 Runable 接口。
当调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的 run() 方法。
package JavaThread.Create; public class CreateByThread extends Thread{ @Override public void run() { for (int i = 0; i<50; i++){ System.out.println(Thread.currentThread().getName()+" "+i); } } public static void main(String[] args) { CreateByThread t1 = new CreateByThread(); CreateByThread t2 = new CreateByThread(); t1.start(); t2.start(); } }
实现接口 对比 继承Thread
实现接口会更好一些,因为:
- Java 不支持多重继承,因此继承了 Thread 类就无法继承其它类,但是可以实现多个接口;
- 类可能只要求可执行就行,继承整个 Thread 类开销过大。