多线程
一、简介
- 线程(Thread):是程序执行流的最小单元,是系统独立调度和分配CPU(独立运行)的基本单位。
- main()是主线程,是系统入口,用于执行整个程序。
- 进程(Process):是资源分配的基本单位。一个进程包括多个线程。
- 例如、QQ、微信、浏览器
- 多线程:同一时刻执行多个线程。
- 例如,用浏览器一边下载,一边听歌
- 多进程:同时执行多个程序。
- 例如,同时运行QQ、微信、浏览器
二、线程创建
1、方法—Thread类
-
自定义线程类,继承Thread类
-
重写run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
//创建线程方法一:继承Thread类,重写run()方法,调用start()启动线程 public class TestThread extends Thread{ @Override public void run() { //run方法线程体 System.out.println("run方法线程体"); } //主线程 public static void main(String[] args) { //创建线程对象 Thread t1 = new TestThread(); Thread t2 = new TestThread(); //调用start()启动线程 t1.start(); t2.start(); } }
2、方法—Runnable接口
-
自定义MyRunnable类实现Runnable接口
-
重写run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
//创建线程方法二:实现Runnable接口,重写run()方法,调用start()启动线程 public class MyRunnable implements Runnable{ @Override public void run() { //run方法线程体 System.out.println("run方法线程体"); } //主线程 public static void main(String[] args) { //创建Runnable接口实现类对象 MyRunnable t1 = new MyRunnable(); MyRunnable t2 = new MyRunnable(); //创建线程对象,通过线程对象来调用start()启动线程(代理) new Thread(t1).start(); new Thread(t2).start(); } }
龟兔赛跑例子:
//模拟龟兔赛跑 public class Race implements Runnable{ //胜利者 private static String winner; @Override public void run() { for (int i = 0; i <= 100; i++) { //模拟兔子休息 if(Thread.currentThread().getName().equals("兔子")){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } //判断比赛是否结束 boolean flag = gameover(i); //比赛结束,停止程序 if(flag){ break; } System.out.println(Thread.currentThread().getName()+"==>跑了"+i+"步"); } } //判断比赛是否结束 public boolean gameover(int steps){ //判断是否存在胜利者 if(winner!=null){ //存在胜利者 return true; }{ if(steps>=100){ winner = Thread.currentThread().getName(); System.out.println("winner is"+winner+"!!!"); return true; } } return false; } public static void main(String[] args) { Race race = new Race(); //同一个赛道,兔子和乌龟一起跑 new Thread(race,"兔子").start(); new Thread(race,"乌龟").start(); } }
3、方法—Callable接口(了解)
-
实现Callable接口,需要返回值类型
-
重写call()方法,需要抛出异常
-
创建目标对象
-
创建执行服务
-
提交执行
-
获取结果
-
关闭服务
import java.util.concurrent.*; //创建线程方法三:实现Callable接口,重写call()方法,创建目标对象、创建执行服务、提交执行、获取结果、关闭服务 public class MyCallable implements Callable { @Override public Object call() throws Exception { System.out.println("call方法线程体"); return true; } //主线程 public static void main(String[] args) throws ExecutionException, InterruptedException { //创建目标对象 MyCallable t1 = new MyCallable(); MyCallable t2 = new MyCallable(); //创建执行服务 ExecutorService executorService = Executors.newFixedThreadPool(2); //提交执行 Future<Boolean> result1 = executorService.submit(t1); Future<Boolean> result2 = executorService.submit(t2); //获取结果 boolean r1 = result1.get(); boolean r2 = result2.get(); //关闭服务 executorService.shutdownNow(); } }
三、静态代理
-
真实对象和代理对象都要实现同一个接口
-
代理对象必须要代理真实角色
-
代理对象可以做很多真实对象做不了的事情,真实对象只需要做自己该做的事情
public class StaticProxy { public static void main(String[] args) { //new Thread(()-> System.out.println("Lambda表达式")).start(); new Wedding(new You()).HappyMarry(); } } //接口 interface Marry{ void HappyMarry(); } //真实角色,实现接口 class You implements Marry{ //重写接口 @Override public void HappyMarry() { System.out.println("真实角色实现接口"); } } //代理角色,实现接口 class Wedding implements Marry{ //代理角色代理的真实对象 private Marry target; public Wedding(Marry target) { this.target = target; } //重写接口 @Override public void HappyMarry() { before(); this.target.HappyMarry();//真实对象 after(); } private void before() { System.out.println("代理对象实现xxx1"); } private void after() { System.out.println("代理对象实现xxx2"); } }
四、Lambda表达式
-
作用:简洁
-
函数式接口才可以用Lambda表达式
-
步骤:
-
定义一个接口
-
lambda表达式
public class TestLambda2 { public static void main(String[] args) { AServices aServicesImpl = (int n)->{ System.out.println("Lambda学习"+n);}; //简化参数类型 aServicesImpl = (n)->{ System.out.println("Lambda学习"+n);}; //简化():如果有多个参数,就不能简化() aServicesImpl = n
-