创建线程的几种方式
创建线程有四种方式:
1.继承Thread类
public class MyThread00 extends Thread { public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "在运行!"); } } }
public static void main(String[] args) { MyThread00 mt0 = new MyThread00(); mt0.start(); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "在运行!"); } }
2.实现Runnable接口
public class MyThread01 implements Runnable { public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "在运行!"); } } }
public static void main(String[] args) { MyThread01 mt0 = new MyThread01(); Thread t = new Thread(mt0); t.start(); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "在运行!"); } }
3.通过FutureTask来创建
public class CallableThread implements Callable<String>{ @Override public String call() throws Exception { this.doSomething(); return "hello"; } private void doSomething() { System.out.println("CallableThread doSomething method!"); } }
public static void main(String[] args) { CallableThread callable = new CallableThread(); FutureTask<String> task = new FutureTask<String>(callable); Thread thread = new Thread(task); thread.start(); try { System.out.println(task.get()); } catch (Exception e) { e.printStackTrace(); } }
4. 通过线程池来创建
public static void main(String[] args) { ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 6, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3) ); Runnable task = new Runnable() { @Override public void run() { System.out.println("xxxx"); } }; threadPool.submit(task); threadPool.shutdown(); }
可用性排序:
线程池 > FutureTask > Runnable > Thread
1、使用继承Thread的方式,意味着该类无法继承其他的类,这样是非常不便利的,所以实现runnable接口要优于继承Thread的方式。
2、FutureTask本质上和直接实现Runnable接口是一样的,但是FutureTask可以通过get方法获取到返回值,所以要优于直接实现Runnable接口的。
3、线程池要优于前面几种,在项目开发的时候是主要使用线程池来创建线程。
3.1、前面几种创建线程都是有创建线程、销毁线程的过程,非常耗费资源,
而线程池执行完线程不会销毁,而是回到线程池成为空闲状态给下一个对象使用,避免频繁创建和销毁线程。
3.2、前面几种方式没有办法控制住在程序当中的创建的线程数量,这样非常不可控,极易造成内存溢出,系统崩溃。