并发编程基础知识
1、JVM使用的线程模型是哪一种?
线程模型包括ULT(用户线程)和KLT(内核线程),JVM规范中没有规定必须使用哪种线程模型,但目前主流的虚拟机使用的都是KLT。
2、Java多线程实现方式
2.1 继承Thread类
继承Thread类,并在子类中重写Thread类的run()方法,然后通过new继承类的实例,实现多线程。缺点是Java只能单继承,无法继承其他类。
public class MyThread extends Thread { @Override public void run() { System.out.println(currentThread().getName() + " started."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(currentThread().getName() + " end."); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { MyThread myThread = new MyThread(); myThread.start(); } } }
2.2 实现Runnable接口
与继承Thread类相比,是更常用的实现多线程的方法。实现Runnable接口,需要重写run()方法。然后通过new实现类的实例,实现多线程。
public class MyThreadImplRunable implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "started"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "end"); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new MyThreadImplRunable().run(); } } }
2.3 实现Callable接口
与线程池配合使用,实现类需要实现Callble接口,重写call()方法,注意call方法是有返回值的。这里通过调用future.get()方法获取返回值,该方法会阻塞直到线程执行结束,并返回结果。
import java.util.concurrent.*; public class MyThreadWithCallable implements Callable { @Override public Object call() throws Exception { System.out.println(Thread.currentThread().getName() + " started"); int sum = 0; for (int i = 0; i < 100; i++) { sum += i; } System.out.println(Thread.currentThread().getName() + " end"); return sum; } public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 100; i++) { Future<?> future = executorService.submit(new MyThreadWithCallable()); Integer count = (Integer) future.get(); System.out.println(count); } } }
2.4 使用Java线程池(单独讲解)
3、Java线程池的使用