一、概念
- 线程(thread):指一个程序内部的一条执行路径。即程序中如果只有一条执行路径,那么这个程序就是单线程的程序。
- 多线程:指从软硬件上实现多条执行流程的技术。例如:消息通信、淘宝、京东系统都离不开多线程技术。
二、多线程
1.继承 Thread 类实现多线程
-
实现步骤
- 继承 Thread 类
- 重写 run() 方法
- 创建线程对象
- 调用 start() 方法
-
优点:编码简单
-
缺点:存在单继承的局限性,线程类继承Thread后,不能继承其他类,不便于扩展
-
代码示例
public class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " --> run"); } } }
public class ThreadDemo { public static void main(String[] args) { Thread t1 = new MyThread(); Thread t2 = new MyThread(); t1.start(); t2.start(); } }
2.覆写 Runnable() 接口实现多线程(可以使用Lambda表达式)
-
实现步骤
- 定义一个线程任务类MyRunnable实现 Runnable 接口,重写 run() 方法
- 创建MyRunnable任务对象
- 把MyRunnable任务对象交给 Thread 对象处理
- 调用线程对象的 start() 方法启动线程
-
优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强。
-
缺点:编程多一层对象包装,如果线程有执行结果是不可以直接返回的。
-
代码示例
public class MyRunnable implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " --> run"); } } }
public class RunnableDemo { public static void main(String[] args) { Runnable runnable = new MyRunnable(); Thread t1 = new Thread(runnable); Thread t2 = new Thread(runnable); t1.start(); t2.start(); } }
3.覆写 Callable 接口实现多线程(JDK1.5新增)
-
实现步骤
-
得到任务对象
-
定义类实现 Callable 接口,重写 call() 方法,封装要做的事情
-
用 FutureTask 把 Callable 对象封装成线程任务对象
-
-
把线程任务对象交给 Thread 处理
-
调用Thread的 start 方法启动线程,执行任务
-
线程执行完毕后,通过FutureTask的 get()
-
方法去获取任务执行的结果
-
-
优点:扩展性强,实现该接口的同时还可以继承其他的类。可以得到线程执行的结果。
-
缺点:编码较复杂
-
代码示例
public class MyCallable implements Callable<Integer> { @Override public Integer call() { int sum = 0; for (int i = 0; i <= 100; i++) { sum += i; } return sum; } }
public class CallableDemo { public static void main(String[] args) throws Exception { Callable<Integer> callable = new MyCallable(); FutureTask<Integer> task = new FutureTask<>(callable); new Thread(task).start(); System.out.println(task.get()); } }
4.通过线程池启动多线程
-
概念:一个可以复用线程的技术
-
使用原因:如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能
-
代码示例
public class ThreadPoolUtil { private ThreadPoolUtil() { } /** * 线程池 */ private static final ExecutorService THREAD_POOL = new ThreadPoolExecutor( 3, 5, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() ); /** * 执行任务 * @param runnable 任务内容 */ public static void execute(Runnable runnable) { THREAD_POOL.execute(runnable); } /** * 关闭线程池 */ public static void shutdown() { THREAD_POOL.shutdown(); } }
public class ThreadPoolDemo { public static void main(String[] args) { Runnable runnable = () -> { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " --> run"); } }; ThreadPoolUtil.execute(runnable); ThreadPoolUtil.execute(runnable); ThreadPoolUtil.shutdown(); } }