在Java开发中,在处理简单的逻辑时我们可能用不到多线程的使用,但是在处理复杂的高并发业务时,我们肯定会使用到多线程,今天就带大家简单了解下Java创建多线程的四种方式。
继承Thread类
public class T { static class MyThread extends Thread { @Override public void run() { System.out.println("Hello MyThread!"); } } public static void main(String[] args) { Thread t = new MyThread(); t.start(); } }
实现Runnable接口
public class T { static class MyRun implements Runnable { @Override public void run() { System.out.println("Hello MyRunnable!"); } } public static void main(String[] args) { Thread t = new Thread(new MyRun()); t.start(); } }
实现Callable接口
import java.util.concurrent.Callable; import java.util.concurrent.Future; public class T { static class MyCallable implements Callable<String> { @Override public String call() throws Exception { return "Hello MyCallable!"; } } public static void main(String[] args) { MyCallable myCallable = new MyCallable(); FutureTask futureTask = new FutureTask<>(myCallable); new Thread(futureTask).start(); try { String msg = (String) futureTask.get(); System.out.println(msg); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (ExecutionException e2) { e2.printStackTrace(); } } }
线程池的创建
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class T { static class MyCallable1 implements Callable<String> { private String msg; public MyCallable1(String msg){ this.msg = msg; } @Override public String call() throws Exception { return "Hello MyCallable " + msg; } } public static void main(String[] args) { ExecutorService e= Executors.newFixedThreadPool(10); Future f1=e.submit(new MyCallable1("1")); Future f2=e.submit(new MyCallable1("2")); Future f3=e.submit(new MyCallable1("3")); try { System.out.println(f1.get()); System.out.println(f2.get()); System.out.println(f3.get()); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (ExecutionException e1) { e1.printStackTrace(); } e.shutdown(); } }
注意:上面只是带大家了解下Java创建多线程的四种方式,当然在实际业务中并不建议大家这样创建多线程,而是应该通过线程池的方式去创建和管理多线程。
阿里巴巴Java开发手册关于并发处理的规范:
【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问 题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这 样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
CachedThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。